2011-12-28 19 views
7

Ho una DLL compilata in Delphi 2007 e un esempio che la utilizza in un altro progetto Delphi. Ecco una parte di codice:Chiamare una funzione DLL delphi dal codice C#

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'; 

Ed ecco la mia C# analogica:

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); 

Il punto è che ho provato unico metodo initmodule e gettò un'eccezione: Una chiamata alla funzione PInvoke 'ProjTest! ProjTest.MyClass :: InitModule' ha sbilanciato lo stack. Ciò è probabile perché la firma PInvoke gestita non corrisponde alla firma di destinazione non gestita. Verificare che la convenzione di chiamata ei parametri della firma PInvoke corrispondano alla firma non gestita di destinazione.

Per favore, aiutami con questo. Come dovrei descrivere queste funzioni DLL in C#?

risposta

11

Non è possibile chiamare quella DLL da C#. Il problema principale sono i due callback of object. Non c'è modo in C# per abbinarlo. Sarà necessario modificare la DLL esistente o aggiungere una DLL adattatore intermedio. Così com'è, la tua DLL è accessibile solo da Delphi o C++ Builder.

Se è possibile modificare la DLL, la modifica che è necessario apportare è rimuovere of object. Se è necessario che il callback agisca su un'istanza, sarà necessario passare l'istanza come parametro. Tuttavia, i delegati di C# possono eseguire il wrapper di tutto ciò in modo trasparente in modo che sia necessario passare l'istanza come parametro solo se è necessario che la DLL sia accessibile da altre lingue, ad es. Delphi.

L'altro problema è il parametro di array aperto. Anche questo non è facilmente accessibile da altre lingue. Sebbene ci siano tricks, suggerirei di passare un riferimento al primo elemento piuttosto che ad un array aperto. Gli array aperti sono unici per Delphi.

Inoltre, non capisco perché si utilizzi il tipo byte per contenere la lunghezza dell'array. Dovresti usare Integer per questo. Non c'è niente da guadagnare dall'uso di byte e semplicemente inviti l'overflow. Inoltre, MainWindowHandle non deve essere THandle in Delphi. Dovrebbe essere HWND.

La mia raccomandazione a voi sarebbe quella di modificare la DLL per avere un'interfaccia C compatibile e quindi essere accessibile da tutte le lingue che lo supportano. In pratica ciò lo renderebbe accessibile da tutti i linguaggi di programmazione tradizionali.

+0

Perché il voto negativo? –

Problemi correlati