Вызов неуправляемых функций из управляемого кода
Чтобы вызвать неуправляемую функцию из управляемого кода, необходимо объявить прототип функции в C# со следующими характеристиками:
- Имеет то же имя, что и неуправляемая функция
- Имеет совместимые параметры и типы возврата
- Заявляется как
static - Заявляется как
extern - Имеет
DllImportAttribute, идентифицирующий местоположение библиотеки
Кроме того, неуправляемая функция должна быть экспортирована с помощью связи C. С помощью связи C можно избежать «манглинг» имен и других проблем с Application Binary Interface (ABI), которые возникают при связи C++-style.
Эти управляемые объявления можно разместить в любом удобном месте вашего кода C#: например, объявить все в одном классе или объявить отдельные функции в тех классах, где они используются.
Примечание: Неуправляемые функции могут возвращать только blittable типы в управляемый код. Blittable типы включают примитивные значения и структуры и массивы, которые содержат только blittable типы.
Например, собственный плагин может определить следующую функцию. Как написано, вы можете скопировать ее непосредственно в файл исходного кода C++ в вашем проекте Unity, который Unity компилирует и связывает статически:
extern "C" {
void SendString(const char* message) {
printf("%s\n", message); // Shown in Player.log
fflush(stdout);
}
}
Для создания того же кода, что и предкомпилированная динамическая библиотека, вы должны также экспортировать каждую функцию, чтобы динамический загрузчик мог найти ее. Определите макрос экспорта и префиксируйте каждую экспортируемую функцию им (например, EXPORT_API void SendString(...)). Плагин с статически связанным исходным кодом не нуждается в этой аннотации:
// Select the annotation by target platform, not by compiler: every Windows
// compiler (MSVC, MinGW, and Clang) needs __declspec(dllexport) to export from a
// DLL, while GCC and Clang use the visibility attribute on other platforms.
#if defined(_WIN32)
#define EXPORT_API __declspec(dllexport)
#elif defined(__GNUC__) || defined(__clang__)
#define EXPORT_API __attribute__((visibility("default")))
#else
#define EXPORT_API
#endif
Примечание: Предкомпилированная динамическая библиотека также требует, чтобы управляемая и неуправляемая стороны использовали одну и ту же конвенцию вызова на 32-битной Windows. См. Вызов управляемых функций из неуправляемого кода для макроса STDCALL, который соответствует конвенции вызова по умолчанию, используемой Unity, и применяйте его таким же образом (например, EXPORT_API void STDCALL SendString(...)).
Ваш класс C# может объявить прототип управляемой функции для SendString() функционируют следующим образом:
[DllImport("__Internal")]
private static extern void SendString(string message);
См. DllImport Атрибут для получения дополнительных сведений о том, как определить библиотеку собственного плагина для загрузки.