2011-12-28 22 views
7

Tengo un archivo DLL compilado en Delphi 2007 y un ejemplo que lo usa en otro proyecto Delphi. Aquí está una parte de código:Llamar a una función delphi DLL desde C# Code

TErrorCallback = function(Msg:PChar):byte of object; 
TSaveEventCallback = function (Line:PChar; HiCode:PChar; LoCode:PChar; MobileNo:PChar):byte of object; 

function InitModule(ErrorCallback:TErrorCallback; SaveEventCallback :TSaveEventCallback; MainWindowHandle:THandle; Sock_Event:integer):byte; stdcall; external 'My.dll' name 'InitModule'; 

function DLLSocketEvent(var msg: TMessage): byte; stdcall; external 'My.dll' name 'DLLSocketEvent'; 

function InitObjList(Objs: array of PChar; NumObjs: byte; Name: PChar):byte; stdcall; external 'My.dll' name 'InitObjList'; 

Y aquí está mi C# analógico:

class Message 
{ 
    unsigned int msg; 
    int wParam; 
    int lParam; 
    int result; 
}; 
delegate byte ErrorCallbackDelegate(string msg); 
delegate byte SaveEventCallbackDelegate(string line, string hiCode, string loCode, string mobileNo); 

[DllImport("My.dll")] 
static extern byte InitModule(ErrorCallbackDelegate errorCallback, SaveEventCallbackDelegate saveEventCallback, IntPtr mainWindowsHandle, Int32 sockEvent); 

[DllImport("My.dll")] 
static extern byte DllSocketEvent(Message msg); 

[DllImport("My.dll")] 
static extern byte InitObjList(string[] objs, byte numObjs, string name); 

El punto es que he intentado único método InitModule y throwed una excepción: Una llamada a la función PInvoke 'ProjTest! ProjTest.MyClass :: InitModule' ha desequilibrado la pila. Esto es probable porque la firma de PInvoke administrada no coincide con la firma de destino no administrada. Compruebe que la convención de llamada y los parámetros de la firma PInvoke coinciden con la firma no administrada de destino.

Por favor, ayúdenme con esto. ¿Cómo debo describir estas funciones DLL en C#?

Respuesta

11

No puede llamar a esa DLL desde C#. El principal problema son las dos devoluciones de llamada of object. No hay forma de que C# coincida con eso. Tendrá que modificar la DLL existente o agregar una DLL de adaptador intermedio. Tal como está, su DLL solo es accesible desde Delphi o C++ Builder.

Si puede modificar el archivo DLL, entonces la modificación que necesita hacer es eliminar el of object. Si necesita la devolución de llamada para actuar en una instancia, deberá pasar la instancia como parámetro. Sin embargo, los delegados de C# pueden envolver todo eso de forma transparente, por lo que solo necesitaría pasar la instancia como parámetro si necesita que la DLL sea accesible desde otros idiomas, p. Delphi.

El otro problema es el parámetro abrir matriz. Tampoco es fácil acceder desde otros idiomas. Aunque hay tricks, recomendaría pasar una referencia al primer elemento en lugar de una matriz abierta. Los arreglos abiertos son exclusivos de Delphi.

Tampoco entiendo por qué está utilizando el tipo byte para mantener la longitud de la matriz. Debe usar Integer para esto. No hay nada que ganar con el uso de bytes y simplemente invitar a desbordamiento. Además, MainWindowHandle no debe ser THandle en Delphi. Debe ser HWND.

Mi recomendación para usted sería modificar la DLL para que tenga una interfaz compatible con C y, por lo tanto, se pueda acceder desde todos los idiomas que lo admitan. En la práctica, esto lo haría accesible desde todos los lenguajes de programación convencionales.

+0

¿Por qué votar abajo? –

Cuestiones relacionadas