2012-05-03 21 views
10

Witam Mam bibliotekę DLL z funkcją, do której muszę zadzwonić. Podpis brzmi:Wywołanie biblioteki dll z C++, C# i ruby ​​

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

Jeśli używam rubinowy wszystko działa poprawnie:

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

Jeśli używam C++ lub C# mam przepełnienie stosu!

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", "{}"); 

Próbowałem wiele wariacji na wywołanie funkcji: winapi Pascal, stdcall, fastcall ... nic nie działa.

DLL nie został stworzony przeze mnie i nie mam nad nim kontroli.

Czy ktoś może mi pomóc z każdą sugestią !?

+0

Możesz rzucić okiem na moje pytanie, aby mieć pomysł. Oto [związek] [1] [1]: http://stackoverflow.com/questions/7153521/pass-multi-dimensional-array-from-managed-code-to-unmanaged-code –

+2

Dlaczego nie użyjesz 'ciągu' dla typów dwóch parametrów w C#? – Ove

+0

Uwierz mi, że dużo szukałem ... :). Próbowałem również z ciągami, ale ze względu na unikanie problemów C# testowałem również ze starym dobrym C++ i nadal przepełnienie stosu! – Joao

Odpowiedz

-5

Wyjątek przepełnienia stosu to błąd wprowadzany w językach microsoft w celu zapobiegania nieskończonej rekursji i zapobiegania interakcjom niekompatybilnych programów. Jeśli twoja metoda dll używa rekurencji, spróbuj przepisać ją z iteracją. W przeciwnym razie, zrób tak, jak powiedział Ove, i spróbuj z ciągami. Jeśli nadal nie działa, Google dla kompatybilnego typu. To wszystko, co mogę powiedzieć, nie znając rzeczywistej metody.

+0

"Wyjątek przepełnienia stosu to błąd wprowadzany w językach microsoft w celu zapobiegania nieskończonej rekursji i zapobiegania interakcjom niekompatybilnych programów. *" Skąd wziął się ten pomysł?Możesz przepełnić stos na każdej platformie, o której wiem ... – ildjarn

+0

Po prostu czytałem to na stronie internetowej Microsoftu, podczas gdy googleing szukał rozwiązania mojego własnego problemu. Rozwiązanie zmieniało to na iteracyjne. – m12

+0

Chodzi mi o to, że nie jest to w żaden sposób związane z językami/platformami Microsoftu, ani też nie zapobiega wzajemnym interakcjom niekompatybilnych programów (czasami jest to spowodowane przez interakcje niekompatybilnych programów). – ildjarn

1

To tylko pomysł, ale AFAIK to może być problem z null- zakończone łańcuchy, const char* myvar ma wartość NUL, ale tablica bajtów nie jest zakończona. Wszystko, co musisz, to zmienić połączenie na ...(String a, String b) i ustawić je jako LPStr.

+0

samo! System.stackoverflow wyjątek – Joao

+0

@ Joao Jestem pewien, że błąd nie został wygenerowany przez samo połączenie (jestem pewien, że powyższe połączenie jest poprawne), może być błąd w metodzie, którą wywołujesz, ponieważ stos -przepływ jest generowany, gdy wiele danych jest na stosie, może to mieć wiele przyczyn. –

+0

Tak, masz rację. ale to, co mnie denerwuje, to fakt, że ruby ​​działa ... Nie znam dobrze ruby ​​i rozważam możliwość, że istnieją pewne fundamentalne różnice między wywołaniami ruby ​​i C++ lub C#, które to powodują. Kolejną kwestią jest być może opcja kompilatora. – Joao

0

nie widzę powodu, dlaczego nie powinno się zmienić swoje wezwanie do

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

trzeba wysłać wskazówek, a nie rzeczywiste wartości/bajty do funkcji.
Zawsze używam tego mapping podczas generowania konwersji typu dla natywnych wywołań funkcji.
To samo dotyczy kodu C++, należy utworzyć zmienne z zawartością i wywołać funkcję.

+0

samo! system.stackoverflow wyjątek – Joao

+0

Czy możesz pokazać swój zmieniony kod? Również użyłbym http://www.dependencywalker.com/ do sprawdzenia problemów z zależnościami. – weismat

+0

Zrobiłem dokładnie tak, jak fragment kodu, a także próbowałem z [MarshalAs (UnmanagedType.LPStr)]. Sposób, w jaki dzwonię, to response = callMethod (key, args); gdzie klucz i argumenty są typu string – Joao