Как код, написанный на одном языке, вызывается из другого языка

Это вопрос, на который я всегда хотел знать ответ, но никогда по-настоящему не задавал.

Как код, написанный на одном языке, особенно на интерпретируемом языке, вызывается кодом, написанным на компилируемом языке.

Например, скажем, я пишу игру на C ++ и передаю на аутсорсинг часть поведения ИИ для написания на Scheme. Как код, написанный на Scheme, достигает точки, которую можно использовать для скомпилированного кода C ++? Как он используется в исходном коде C ++ и как он используется в скомпилированном коде C ++? Есть ли разница в способе его использования?

Связанный

Как несколько языков взаимодействуют в одном проекте?


person Hooray Im Helping    schedule 08.05.2009    source источник
comment
Лучший. Имя. Всегда.   -  person Andrew Sledge    schedule 08.05.2009


Ответы (7)


Нет однозначного ответа на вопрос, который работает везде. В общем, ответ заключается в том, что два языка должны согласовать «что-то» - набор правил или «протокол вызова».

На высоком уровне любой протокол должен определять три вещи:

  • «открытие»: как узнать друг о друге.
  • "связывание": как установить соединение (после того, как они узнают друг о друге).
  • «Призыв»: как на самом деле делать запросы друг к другу.

Детали сильно зависят от самого протокола.

Иногда два языка работают вместе. Иногда два языка соглашаются поддерживать какой-то протокол, определенный извне. В наши дни также часто используется ОС или «среда выполнения» (.NET и Java). Иногда способность действует только в одну сторону («А» может называть «Б», но «Б» не может называть «А»).

Обратите внимание, что это та же проблема, с которой сталкивается любой язык при взаимодействии с ОС. Вы знаете, что ядро ​​Linux не написано на Scheme!

Давайте посмотрим на типичные ответы из мира Windows:

  • C с C ++: C ++ использует искаженный ("искаженный") вариант "протокола C". C ++ может вызывать C, а C может вызывать C ++ (хотя имена иногда могут быть довольно запутанными, и может потребоваться внешняя помощь для перевода имен). Это не только Windows; это обычно верно для всех платформ, которые поддерживают оба. Наиболее популярные ОС также используют "протокол C".

  • VB6 по сравнению с большинством языков: предпочтительный метод VB6 - "протокол COM". Другие языки должны иметь возможность писать COM-объекты, чтобы их можно было использовать из VB6. VB6 также может создавать COM-объекты (хотя и не все возможные варианты COM-объектов).

    VB6 также может использовать очень ограниченный вариант «протокола C», а затем только совершать внешние вызовы: он не может создавать объекты, с которыми можно разговаривать напрямую через «протокол C».

  • Языки .NET: все языки .NET передают компиляцию на один и тот же язык низкого уровня (IL). Среда выполнения управляет коммуникацией, и с этой точки зрения все они выглядят как один и тот же язык.

  • VBScript по сравнению с другими языками: VBScript может использовать только часть протокола COM.

Еще одно замечание: «Веб-службы» SOAP также являются «протоколом вызова», как и многие другие сетевые протоколы, которые становятся популярными. В конце концов, все дело в разговоре с кодом, написанным на другом языке (и при этом запущенным в другом окне!)

person Euro Micelli    schedule 08.05.2009

Обычно код C ++ вызывает интерпретатор для языка сценариев. Степень взаимодействия между скомпилированным кодом и кодом сценария зависит от интерпретатора, но всегда есть способ передать данные между ними. В зависимости от интерпретатора может быть возможно манипулировать объектами с одной стороны с другой стороны, например, функция C ++, вызывающая метод объекта Ruby. Может даже быть способ контролировать выполнение одного из другого.

person Pesto    schedule 08.05.2009

Существует протокол взаимодействия модулей. Вот общий обзор того, как это работает:

  1. Библиотека создается для кода, которым вы хотите «поделиться». Их обычно называют библиотеками DLL или SO, в зависимости от вашей платформы.
  2. Каждая функция, которую вы хотите предоставить (точка входа), будет доступна для привязки к внешнему миру. Существуют протоколы привязки, такие как соглашение о вызовах, в котором указывается порядок передачи параметров, кто очищает стек, сколько параметров сохраняется в регистрах и какие из них и т. Д. Примеры вызовов см. В cdecl, stdcall и т. Д. соглашения здесь.
  3. Затем вызывающий модуль будет статически или динамически связываться с разделяемой библиотекой.
  4. Как только ваша вызывающая библиотека привязана к общей библиотеке, она может указать, что она хочет привязаться к определенной точке входа. Обычно это делается по имени, однако большинство платформ также предлагают возможность привязки по индексу (быстрее, но более хрупко, если ваш модуль изменяется и точки входа переупорядочиваются).
  5. Вы также обычно объявляете функцию, которую хотите вызвать в своем модуле, где-нибудь, чтобы ваш язык мог выполнять статическую проверку типа, знал, что такое соглашение о вызовах и т. Д.

Для вашего сценария вызова Scheme из C ++ интерпретатор Scheme, скорее всего, экспортирует функцию, которая динамически связывается с функцией / объектом Scheme и вызывает ее. Если модуль Scheme скомпилирован, он, вероятно, имеет возможность экспортировать точку входа, чтобы ваш модуль C ++ мог привязаться к ней. Я не очень хорошо знаком со схемой, поэтому кто-то другой, вероятно, сможет ответить на специфику этой конкретной привязки лучше, чем я.

person Adam Markowitz    schedule 08.05.2009
comment
Ха-ха !! Привет, Спарки! Приятно видеть тебя здесь. (Винс) - person veefu; 09.05.2009
comment
Привет, Винс! Давно не виделись. Как ты поживаешь (позвонил мне в FB)? - person Adam Markowitz; 09.05.2009

Вы также можете интегрировать две среды без необходимости компилировать библиотеку интерпретатора внутри вашего исполняемого файла. Вы храните exe и Scheme exe как отдельные программы в вашей системе. Из основного исполняемого файла вы можете записать код схемы в файл, а затем использовать system () или exec () для запуска интерпретатора схемы. Затем вы анализируете вывод интерпретатора схемы.

Предложенный выше подход разделяет бывших участников, и вам не нужно беспокоиться о сторонних зависимостях, они могут быть значительными. Также проблемы остаются в том или ином exe.

Если запуск отдельного исполняемого файла не удовлетворяет вашим требованиям к производительности, вы можете разработать протокол, в котором интерпретатор схемы становится сервером. Вам нужно написать некоторые функции схемы, которые ждут ввода в сокет или файл, оценивать этот ввод, а затем выводить результат в тот же сокет или другой файл. Другая итерация этого - рассмотрение существующих серверов, на которых может уже быть запущен ваш интерпретатор, например, у apache есть модули, которые позволяют писать код на многих языках.

person Marius Seritan    schedule 08.05.2009

Если вы действительно ищете инструменты для этого, как ответ Адама, см. swig.

person Matt    schedule 08.05.2009

С теоретической точки зрения, когда программе A необходимо использовать ресурсы (класс / функции / и т. Д.) Из программы B, речь идет о передаче некоторой информации от A к B и возвращении некоторой информации или выполненных действиях. Таким образом, B должен быть способ, позволяющий A передавать информацию и получать результат.

На практике этот процесс обычно лежит на плечах языков: язык B (программа B написана) сгенерирует протокол и сделает ресурсы в B доступными предопределенным способом, затем язык A (программа A написана на ) предоставит некоторую утилиту / фреймворк, чтобы помочь вызвать открытые ресурсы и получить результаты в соответствии с протоколом B.

Чтобы быть более конкретным в отношении вашего вопроса, для интерпретируемых языков процесс довольно универсален, протокол обычно находится среди строк параметра командной строки, HTTP-запроса и других способов передачи обычного текста. Возьмем первый пример, программа B получит вызов из HTTP-запроса в качестве входных данных, а затем обработает запрос оттуда. Фактический формат ввода полностью определяется программой B.

Такие вещи, как SOAP и т. Д., - это всего лишь способ отрегулировать программы, чтобы они принимали участие в общепринятом стандарте.

person FlyinFish    schedule 08.05.2009

Прошло около десяти лет, но я сделал именно это для своей старшей вершины (ну, я построил нейронную сеть с обратным распространением на языке C и использовал программу-схему, чтобы научить ее). Версия Scheme, которую я использовал, имела компилятор, а также интерпретатор, и я смог создать ее как файл .o. Я не знаю, какую версию схемы я использовал, но похоже, что RScheme превратит код вашей схемы в C.

person Matt Poush    schedule 08.05.2009