簡體   English   中英

如何用另一種語言調用用一種語言編寫的代碼

[英]How does code written in one language get called from another language

這是一個我一直想知道答案的問題,但從未真正問過。

一種語言編寫的代碼,特別是解釋語言,如何被編譯語言編寫的代碼調用。

例如,假設我正在用C ++編寫游戲,並且我將一些AI行為外包給要用Scheme編寫。 如何用Scheme編寫的代碼到達編譯的C ++代碼可用的點? 它是如何被C ++源代碼使用的,它是如何被C ++編譯的代碼使用的? 它的使用方式有所不同嗎?

有關

多語言如何在一個項目中進行交互?

對於無處不在的問題,沒有一個單一的答案。 一般來說,答案是兩種語言必須就“某事” - 一組或規則或“呼叫協議”達成一致。

在高級別,任何協議都需要指定三件事:

  • “發現”:如何找到彼此。
  • “鏈接”:如何建立連接(在他們彼此了解之后)。
  • “調用”:如何實際向對方發出請求。

細節在很大程度上取決於協議本身。

有時兩種語言合謀共同努力。 有時兩種語言同意支持一些外部定義的協議。 目前,操作系統或“運行時環境”(.NET和Java)也經常被涉及。 有時這種能力只有一種方式(“A”可以稱為“B”,但“B”不能稱為“A”)。

請注意,這與任何語言在與OS通信時面臨的問題相同。 你知道,Linux內核不是用Scheme編寫的!

讓我們看看來自Windows世界的一些典型答案:

  • C與C ++ :C ++使用“C協議”的扭曲(“受損”)變體。 C ++可以調用C,而C可以​​調用C ++(雖然名稱有時可能非常混亂,可能需要外部幫助來翻譯名稱)。 這不僅僅是Windows; 在支持兩者的所有平台上通常都是如此。 最流行的操作系統也使用“C協議”。

  • VB6與大多數語言相比 :VB6的首選方法是“COM協議”。 其他語言必須能夠編寫可從VB6使用的COM對象。 VB6也可以生成COM對象(盡管不是每個可能的COM對象變體)。

    VB6也可以說“C協議”的非常有限的變體,然后只在外面進行調用:它不能創建可以通過“C協議”直接對話的對象。

  • .NET語言 :所有.NET語言都將編譯傳遞給相同的低級語言(IL)。 運行時管理通信,從這個角度來看,它們看起來都是相同的語言。

  • VBScript與其他語言 :VBScript只能討論COM協議的一個子集。

還有一點需要注意:SOAP“Web Services”實際上也是一種“調用協議”,就像許多其他基於Web的協議一樣受歡迎。 畢竟,這都是關於用不同語言編寫的代碼(並在另一個框中運行!)

通常,C ++代碼將調用腳本語言的解釋器。 編譯代碼和腳本代碼之間的交互程度取決於解釋器,但始終有一種方法可以在兩者之間傳遞數據。 根據解釋器,可以從另一側操縱一側的對象,例如調用Ruby對象上的方法的C ++函數。 甚至可能有一種方法來控制另一個的執行。

有一個模塊如何通信的協議。 以下是對其工作原理的高級概述:

  1. 為要“共享”的代碼創建庫。 這些通常稱為DLL或SO,具體取決於您的平台。
  2. 您要公開的每個函數(入口點)都可供外界使用以進行綁定。 有如何綁定的協議,例如調用約定,它指定傳遞參數的順序,誰清理堆棧,有多少參數存儲在寄存器中以及哪些參數等等。有關調用的示例,請參閱cdecl,stdcall等。 這里的約定。
  3. 然后,調用模塊將靜態或動態綁定到共享庫。
  4. 一旦您的調用庫綁定到共享庫,它就可以指定它想要綁定到特定入口點。 這通常通過名稱來完成,但是大多數平台還提供了通過索引進行綁定的選項(如果模塊更改並且重新排序入口點,則更快,更脆)。
  5. 您通常也會在模塊中的某個地方聲明要調用的函數,以便您的語言可以執行靜態類型檢查,知道調用約定是什么等。

對於從C ++調用Scheme的場景,Scheme解釋器很可能導出一個動態綁定到Scheme函數/對象並調用它的函數。 如果編譯了Scheme模塊,它可能有導出入口點的選項,因此您的C ++模塊可以綁定到該模塊。 我對Scheme不太熟悉,所以其他人可能比我更能回答那個特定綁定的細節。

您還可以集成這兩個環境,而無需在可執行文件中編譯解釋器的庫。 您將exe和Scheme exe保存為系統上的單獨程序。 從主exe文件中,您可以將Scheme代碼寫入文件,然后使用system()或exec()來運行scheme解釋器。 然后解析方案解釋器的輸出。

上面提出的方法使得exes保持獨立,您不必擔心第三方依賴,它們可能很重要。 問題仍然存在於一個或另一個exe中。

如果運行單獨的exe不滿足您的性能要求,您可以設計一個Scheme解釋器成為服務器的協議。 您需要編寫一些等待套接字或文件輸入的Scheme函數,然后輸入eval然后將結果輸出到同一個套接字或不同的文件。 另一個迭代是查看可能正在運行解釋器的現有服務器,例如apache具有允許以多種語言編寫代碼的模塊。

如果你真的在尋找工具來做這樣的事情,那就是亞當的反應,請看看swig

從理論的角度來看,當程序A需要使用來自程序B的資源(類/函數/等)時,它是關於將一​​些信息從A傳遞到B,並獲取一些信息或執行某些操作。 因此需要B提供的方法允許A傳遞信息並獲得結果。

在實踐中,它通常位於語言的肩膀上來處理這個過程:語言B(程序B被寫入)將生成一個協議,並以預定義的方式使B中的資源可用,然后語言A(程序A寫入)將提供一些實用程序/框架來幫助調用公開的資源並根據B的協議獲得結果。

為了更具體地解決您的問題,對於解釋型語言,該過程相當普遍,協議通常在命令行參數,HTTP請求和其他傳輸純文本的方式之間。 舉一個例子,程序B將接收來自HTTP請求的調用作為輸入,然后從那里處理請求。 輸入的實際格式完全由程序B決定。

諸如SOAP之類的東西只是一種規范程序以在共同商定的標准中獲取輸入的方式。

這已經是十年左右了,但我為我的高級頂點做了這個(好吧,我在C中構建了一個反向傳播神經網絡,並使用一個計划程序來教它)。 我正在使用的Scheme版本有一個編譯器和一個intepreter,我能夠將它構建為.o文件。 我不知道我正在運行的方案版本,但似乎RScheme會將您的方案代碼轉換為C.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM