2012-05-03 21 views
10

Ciao Ho una DLL con una funzione che ho bisogno di chiamare. La firma è:Chiamare una DLL c da C++, C# e ruby ​​

const char* callMethod(const char* key, const char* inParams); 

Se uso rubino tutto funziona bene:

attach_function :callMethod, [:string, :string], :string 

Se uso C++ o C# ho overflow dello stack!?

C#:

[DllImport("DeviceHub.dll", CallingConvention = CallingConvention.Cdecl)] 
private unsafe static extern IntPtr callMethod(
    [MarshalAs(UnmanagedType.LPArray)] byte[] key, 
    [MarshalAs(UnmanagedType.LPArray)] byte[] inParams 
); 

System.Text.UTF8Encoding encoding = new UTF8Encoding(); 
IntPtr p = callMethod(encoding.GetBytes(key), encoding.GetBytes(args)); // <- stack overflow here 

C++:

extern "C" 
{ 
typedef DllImport const char* ( *pICFUNC) (const char*, const char*); 
} 
HINSTANCE hGetProcIDDLL = LoadLibrary(TEXT("C:\\JOAO\\Temp\\testedll\\Debug\\DeviceHub.dll")); 
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"callMethod");*  pICFUNC callMethod; 
callMethod = (pICFUNC) lpfnGetProcessID; 
const char * ptr = callMethod("c", "{}"); 

ho provato un sacco di varianti per la funzione di chiamata: WINAPI, PASCAL, stdcall, fastcall, ... niente funziona.

La DLL non è stata creata da me e non ho il controllo su di esso.

Qualcuno può aiutarmi con qualche suggerimento !?

+0

Puoi dare un'occhiata alla mia domanda per avere un'idea. Ecco un [link] [1] [1]: http://stackoverflow.com/questions/7153521/pass-multi-dimensional-array-from-managed-code-to-unmanaged-code –

+2

Perché non usi 'string' per i tipi dei due parametri in C#? – Ove

+0

Credimi, ho cercato molto ... :). Ho anche provato con le stringhe ma, per evitare problemi C#, ho anche provato con un buon vecchio C++ e con stack overflow! – Joao

risposta

-5

L'eccezione di overflow dello stack è un errore presente nei linguaggi Microsoft per impedire la ricorsione infinita e per impedire l'interazione tra programmi incompatibili. Se il tuo metodo dll utilizza la ricorsione, prova a riscriverlo con l'iterazione. Altrimenti, fai come ha detto Ove e prova con le corde. Se continua a non funzionare, Google per un tipo compatibile. Questo è tutto ciò che posso dire senza conoscere il metodo attuale.

+0

"* L'eccezione di overflow dello stack è un errore che viene introdotto nei linguaggi di Microsoft per impedire una ricorsione infinita e per impedire l'interazione tra programmi incompatibili. *" Dove hai ottenuto questa idea?Puoi sovraccaricare lo stack su qualsiasi piattaforma di cui sono a conoscenza ... – ildjarn

+0

Semplice, l'ho appena letto sul sito Web di Microsoft mentre googleing per una soluzione al mio problema. La soluzione stava cambiando iterativa. – m12

+0

Il mio punto è che non è in alcun modo specifico ai linguaggi/piattaforme Microsoft, né è lì per impedire ai programmi incompatibili di interagire tra loro (a volte è causato da programmi incompatibili che interagiscono tra loro). – ildjarn

1

Questa è solo un'idea, ma per quanto ne so questo potrebbe essere un problema con il null- stringhe terminate, const char* myvar è terminato da null ma un array di byte non lo è. Tutto ciò che devi fare è cambiare la chiamata a ...(String a, String b) e metterli in ordine di marcia come LPStr.

+0

stessa cosa! System.stackoverflow exception – Joao

+0

@Joao Sono sicuro che l'errore non è generato dalla chiamata stessa (sono sicuro che la chiamata sopra è corretta), potrebbe esserci un errore nel metodo che chiamate perché uno stack -overflow viene generato quando ci sono molti dati in pila, questo può avere molte ragioni. –

+0

sì hai ragione. ma la cosa che mi infastidisce è il fatto che il rubino funzioni ... non annuisco molto bene il ruby ​​e sto considerando la possibilità che ci siano alcune differenze fondamentali tra la chiamata di ruby ​​e la chiamata C++ o C# che fa sì che ciò accada. Un altro problema è forse qualche opzione del compilatore. – Joao

0

vedo alcun motivo per cui non si dovrebbe cambiare la vostra chiamata a

[DllImport("DeviceHub.dll", CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern string callMethod(
string key,
string inParams
);

È necessario inviare i puntatori, non i veri valori/byte alla funzione.
Io uso sempre questo mapping durante la generazione della conversione del tipo per le chiamate di funzione native.
Lo stesso vale per il codice C++, è necessario creare variabili con il contenuto e chiamare la funzione.

+0

stessa cosa! system.stackoverflow exception – Joao

+0

Potresti mostrare il tuo codice modificato? Inoltre, utilizzerei http://www.dependencywalker.com/ per verificare la presenza di problemi dipendenti. – weismat

+0

Ho fatto esattamente come il tuo frammento di codice e ho anche provato con [MarshalAs (UnmanagedType.LPStr)]. Il modo in cui sto chiamando è response = callMethod (key, args); dove key e args sono di tipo stringa – Joao