Я пытаюсь использовать систему частиц SPARK в OpenTK.
Мой проект содержит заголовочные файлы в папках, всего два заголовочных файла, в которые входят только остальные, и папки также содержат исходные файлы.
До сих пор я пробовал несколько подходов, но у меня пока ничего не получалось, вот что я пробовал:
Это написание некоторого кода в вашем C ++ проекте, который собрал dll, а затем с использованием DllImport
атрибут в C # (который, очевидно, нуждается в using System.Runtime.InteropServices;
). Я обнаружил сложный способ, что это не работает с классами, оно работает только для методов вне классов, поэтому этот подход был неэффективным.
Это написание класса, который содержит указатель на исходный класс. Я обнаружил, что трудности на самом деле возникают из-за вызова неуправляемого кода (без автоматического управления памятью) из управляемого кода, поэтому необходимы классы-обертки, и поэтому вам нужно переопределить сигнатуры методов и позволить им вызывать оригинальные методы.
Конечно, у этого есть свои преимущества, например, более точное наименование классов и методов, но библиотека настолько велика, что вы можете увидеть, как это работает.
Это хороший подход, особенно с xInterop ++. Я был очень оптимистичен по этому поводу и думал, что это сработает, он говорит: «дайте мне файлы .h и dll, и я создам .NET dll для вас». Хорошо, но это дает ошибку; вкратце:
Вы должны убедиться, что файлы .h и dll соответствуют друг другу и что
Библиотека работает в проекте C ++.
Я пробовал несколько вещей, чтобы справиться с этой ошибкой:
_declspec(dllexport)
,Вот где я застрял, вот ошибки компоновщика, которые я получаю:
main.obj: ошибка LNK2019: неразрешенный внешний символ «void __cdecl
SPK :: swapParticles (класс SPK :: Частица &, класс СПК :: Частица &) «(? swapParticles @ SPK @@ YAXAAVParticle @ 1 @ 0 @ Z) ссылка на функцию
«private: void __thiscall SPK :: Pool :: swapElements (класс SPK :: Particle &, класс СПК :: Частица
&) «(? swapElements @? $ Pool @ VParticle @ SPK @@@ SPK @@ AAEXAAVParticle @ 2 @ 0 @ Z)
main.obj: ошибка LNK2001: неразрешенный внешний символ «unsigned int
SPK :: randomSeed «(? RandomSeed @ SPK @@ 3IA) main.obj: ошибка LNK2001:
неразрешенный внешний символ «unsigned long const SPK :: NO_ID» (? NO_ID @ SPK @@ 3KB) main.obj: ошибка LNK2001: неразрешенный внешний символ
«public: static float const * const SPK :: Transformable :: IDENTITY» (? IDENTITY @ Transformable @ SPK @@ 2QBMB)
Это код, который вызвал эти ошибки:
#include "Extensions/Emitters/SPK_RandomEmitter.h"
using namespace SPK;
int main()
{
RandomEmitter e;
e.changeFlow(6);
e.getFlow();
return 0;
}
Так что это моя проблема, прошу прощения за слишком много объяснений, но я провел трехдневный поиск, не найдя никакого решения.
библиотека очень большая, поэтому необходимо автоматическое решение.
Это очень, очень недружелюбная библиотека C ++, с которой приходится взаимодействовать. Скажи идею, что pinvoke может работать, классы C ++ требуют оболочек C ++ / CLI. Существует множество классов с множеством маленьких методов. Библиотека зависит от композиции для создания эффектов, поэтому любой подход, который пытается взаимодействовать с несколькими классами Бога, является мертвой авеню.
Самая значительная опасность заключается в том, что он сильно зависит от множественного наследования. Не поддерживается в .NET, это победит любой инструмент, который автоматически генерирует оболочки. Также обратите внимание, что он поддерживает только рендеринг OpenGL, а не очень популярный графический API в Windows.
Библиотека привлекательна и существует уже довольно давно, но пока никто не смог успешно перенести ее на .NET. Это неудивительно. В моем мнение, у тебя нет шансов. Только переписать может работать.
PInvoke — это способ сделать то, что вы ищете. Не имеет значения, есть ли у вас или нет код для этой DLL, если вы знаете сигнатуру функции.
Взгляните на эти статьи из MSDN и проекта кода, которые охватывают основы PInvoke:
Редактировать:
Существуют инструменты, которые могут генерировать подпись DllImport для вас. Я не пробовал ничего из этого сам. Посмотри:
Надеюсь, это поможет.
Если ваш родной dll экспортирует некоторые классы, я настоятельно рекомендую создать еще один родной DLL-обертку для исходного. Он должен экспортировать несколько функций и никаких классов вообще.
Экспортированный функционал может быть что-то вроде:
my_lib_create_context( void ** const ppContext );
my_lib_delete_context( void * const pContext );
my_lib_do_something( void * const pContext, T param1, T param2 );
внутри my_lib_create_context()
создать экземпляр вашего класса и передать указатель обратно через ppContext параметр.
внутри my_lib_do_something()
бросить pContext к указателю вашего типа класса и использовать его.
Кроме того, при написании вашей обертки обратите внимание на соглашение о вызовах, потому что вам нужно будет передать эту информацию в мир .NET (я думаю, что stdcall является значением по умолчанию, если оно явно не определено).
РЕДАКТИРОВАТЬ:
Что касается этой части о том, как это сделать:
Создайте новое C ++ решение / проект, выберите тип DLL. Затем добавьте файл .def в этот проект. Добавьте к этому файлу это:
ЭКСПОРТ
my_lib_create_context @ 1
my_lib_delete_context @ 2
my_lib_do_something @ 3
Затем добавьте заголовочный файл, в который вы поместите сигнатуры функций, например:
typedef void * SomeContext;
extern "C"{
int __stdcall my_lib_create_context( /* [ out ] */ SomeContext * ppContext );
int __stdcall my_lib_delete_context( /* [ in ] */ SomeContext pContext );
// TO DO: ... you get it by now...
}
Реализуйте эти функции в файле .cpp. Как только вы закончите, создайте оболочку в C # для этой DLL и используйте ее.
Хм P / Invoke вызов GetProcessAdress .. поэтому проблема импорта ABI так себе ..
http://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class
вот ваш ответ отдать должное этим парнем