Я опытный инженер-программист, но несколько новичок в C#. У меня есть DLL, которая состоит из объектов C++ с интерфейсом C, как показано. Я использовал этот интерфейс C, потому что не был уверен, есть ли способ доступа к точкам входа C++ в DLL из моего приложения C#.Как передать указатель объекта из и в DLL?
__declspec(dllexport) void *Constructor();
__declspec(dllexport) void Destructor(void *pObj);
__declspec(dllexport) int Method(void *pObj, char *pSrcDst, int len);
Это код C для вышеуказанного интерфейса.
extern "C" void *Constructor()
{
return (void *)new Object;
}
extern "C" void Destructor(void *pObj)
{
delete (Object *)pObj;
}
extern "C" int Method(void *pObj, char *pSrcDst, int len)
{
if (!pObj) return 0;
return ((Object *)pObj)->Method(pSrcDst, len);
}
Пока все хорошо. Теперь мне нужно иметь доступ к этому интерфейсу из приложения C#. Из того, что я узнал, я реализовал следующий интерфейс C#.
unsafe public class Wrapper
{
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
IntPtr Constructor();
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
void Destructor(IntPtr pObj);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
int Method(IntPtr pObj, [In,Out] byte[] pSrcDst, int len);
И вот код C#, который использует вышеуказанный интерфейс.
private IntPtr pObject;
public object()
{
pObject = Wrapper.Constructor();
}
~object()
{
Wrapper.Destructor(pObject);
}
public override byte[] method()
{
byte[] bytes = new byte[100];
int converted = Wrapper.Method(pObject, bytes, bytes.length);
return bytes;
}
Код утверждает как при вызове Wrapper.Method, а также Wrapper.Destructor. Я предполагаю, что я неправильно обрабатываю указатель на объект. Какие-либо предложения?
Что значит «код утверждает»? Вы получаете сообщение об ошибке? – svick
Да, «обнаружен PInvokeStackImbalance». –
Имейте в виду, что большинство компиляторов предполагают, что 'extern 'C' 'функции не генерируют исключений (особенно если код C вызывает их), поэтому вы захотите обернуть бит' new Object() 'в блок исключений, чтобы предотвратить исключение любых исключений (в частности, 'std :: bad_alloc') из экранирования. –