Sziasztok!
Adott egy probléma, melyben egy szerveren futó ősrégi programmal kellene kommunikálnom egy most készülő .NET-es programból. Ehhez biztosítva van egy szintén ősrégi C++-ban írt .dll, viszont a .dll függvényeinek hívásakor egyszerűen semmi sem történik. A .dll szerintem rendben van, mert van egy szintén ősrégi kliens program, ami ha betöltjük a .dll-t akkor nagyon szépen kommunikál a szerveren futó programmal. A .dll-hez van dokumentáció, ami nem túl részletes, és van hozzá egy header-fájl is, amivel egy kicsit többre jutottam.
Példa a header-ben lévő függvény deklarációra:
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
extern "C" DLL_API void __stdcall foo(int, int, char*, char*, int);
A most készülő .NET-es programból a következő módon próbálom meghívni ezt a függvényt:
(Nyelv: C#)
[DllImport("DLL neve", EntryPoint="foo", CallingConvention=StdCall)]
public static extern void Foo(int param1, int param2, string param3, string param4, int param5);
Viszont ahogy az elején is említettem a függvény hívásakor nem történik semmi.
Már minden általam eddig ismert, és frissen megismert dolgot próbáltam, de a hívás akkor is "süket fülekre talál".
Van esetleg valaki aki találkozott már ilyen problémával és sikerült megoldania a dolgot?
Szívesen venném ha megosztaná velem a tapasztalatait.
A válaszokat és a jó tanácsokat előre is köszönöm.
- 1511 megtekintés
Hozzászólások
A C# -> C hívási konvenció leképzés az egyik ami hibás lehet.
Mi az, hogy nem történik semmi? Exceptiön nincs-> a szimbólumot megtalálja és rá is teszi a vezérlést. Aztán visszatér, de nem történik meg aminek meg kell történni? Hibajelzés semmi?
Amit csinálnék:
* sima C programmal megnézni, hogy működik-e a dll használata?
* Ha működik beledebuggolni a C programba, hogy minek kellene a stacken/regiszterekben lenni, ha jó a paraméterátadás
* Beledebuggolni a .NET+dll-be, hogy mi van a stacken, amikor meghívja a dll függvényt (a dll függvény belépési pontjára kell tenni a breakpointot)
* Ebből kiderül, hogy mi a hibás -> megjvítani, örülni
Persze a doksi olvasgatása sem elvetendő debuggolás előtt/helyett :-). A string->char* konverzió tuti, hogy rendben van? Nem valami más típussá konvertálja a .NET ezeket a paramétereket?
Ha semmi nem működik, akkor külön kipróbálnám a paraméterek .NET->C átadását egyesével saját C-nyelvű DLL-lel típusonként. Aztán ha működik, akkor írnék egy C függvényt, amit .NET-ből hívnék és továbbhívnám az eredeti függvényt belőle. De ezt már szigorúan a leggyakoribb példaprogram beállításokkal. Hátha a hívási konvencióval, vagy valami hasonlóvan van probléma.
- A hozzászóláshoz be kell jelentkezni
Én is a stringre gyanakodnék. RTFM: https://docs.microsoft.com/en-us/dotnet/framework/interop/default-marsh…
- A hozzászóláshoz be kell jelentkezni
A futás során nincs semmiféle exception.
A konverzióra eddig azért nem gyanakodtam, mert sok .dll-el (pl: kernel32.dll) próbálkoztam (csak sajáttal nem) és nem volt probléma a paraméter átadással.
De minden esetre kipróbálom a javaslatodat, és írok egy saját .dll-t amin először kipróbálom a paraméter átadást, aztán pedig az "Ős" .dll függvényeinek hívását.
- A hozzászóláshoz be kell jelentkezni
Az ősrégi azért 32 bites? A .NET kódod explicit x86 fordítod? Ilyenkor az AnyCPU nyűgös szokott lenni.
- A hozzászóláshoz be kell jelentkezni
Nem, AnyCPU-ra fordul. Köszi a tippet.
- A hozzászóláshoz be kell jelentkezni
Igen, Java+dll (so) esetén erre figyelni kell, hogy 32 bites JVM-hez 32 bites dll kell és 64 bites JVM-hez 64 bites dll. 32-64 bit között nem tud függvényhatáron váltani a processz.
- A hozzászóláshoz be kell jelentkezni
Hát sajnos ha x86-ra fordítom az sem oldja meg a problémát.
- A hozzászóláshoz be kell jelentkezni
De akkor kellene hibaüzenetet kapnod, hogy ez nem kompatibilis, vagy valami ilyesmi.
Legalábbis Java esetén ez van, ha más architektúrára való dll-t próbálnék betölteni.
- A hozzászóláshoz be kell jelentkezni
Nincs semmi hibaüzenet. Betöltöm a .dll-t most már C++-os mini projektbe és meghívok egy véletlenszerű függvényt, és továbbra sem történik semmi.
- A hozzászóláshoz be kell jelentkezni
Én nem foglalkozok ilyenekkel, de valami hasonló problémánk volt pár éve egy projektben, aki szenvedett vele, valami olyasmi megoldást talált, hogy becsomagolja a hívást egy C++/CLI kódba, azt hívja C#-ból, és akkor nem az utóbbiban kell szenvedni a két világ összeeegyeztetésével, mert az előbbinek az a dolga.
- A hozzászóláshoz be kell jelentkezni
+1: managed C++ az.
--
https://naszta.hu
- A hozzászóláshoz be kell jelentkezni
A Managed C++ az előd volt, már C++/CLI van helyette. (Nem csak a név új, a szintaxis is.)
- A hozzászóláshoz be kell jelentkezni
meg csinalnek egy mini debug dll-t, benne ugyanugy a foo fuggvennyel, es abban szepen kidumpolnam a parameterket:
void __stdcall foo(int param1, int param2, char* param3, char* param4, int param5)
{
printf("param1: %d\n", param1);
printf("param3: %p: %s\n", param3, param3);
...
}
aztan ezt a dllt hivogatva a netes programbol, latod hogy valojaben milyen parameterek ernek at.
megjegyzes: tippre ott a string->char* konverzional lesz elrontva valami, es lehet jol irtak meg azt a foo-t, hibas parameterre nem csinal semmit. https://stackoverflow.com/questions/39987435/pass-char-to-c-dll-from-c-…
--
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!
- A hozzászóláshoz be kell jelentkezni
A string -> char* valóban problémás lehet, de szinte az összes variációt kipróbáltam:
- string
- String
- StringBuilder
- byte array
- Marshaling LPStr-re
- A hozzászóláshoz be kell jelentkezni
Ha minden kötél szakad, csinálj egy wrappert neki C++/CLR-ben. Ott ott vannak a .NET-es osztályok is, és minden más is, ami a natív C/C++-ban elérhető.
- A hozzászóláshoz be kell jelentkezni
+1, egyszeru, gyors
- A hozzászóláshoz be kell jelentkezni
Es ha CallingConvention=Cdecl -el probalod?
- A hozzászóláshoz be kell jelentkezni
Akkor kapok egy System.EntryPointNotFoundException-t.
- A hozzászóláshoz be kell jelentkezni
Nincs az api-n egy init szeru fuggveny, amit mindenkepp meg kell hivni a tobbi elott?
- A hozzászóláshoz be kell jelentkezni
Hát a dokumentáció alapján nincs semmi ilyen, sőt a header fájlban sem látok ilyesmit.
- A hozzászóláshoz be kell jelentkezni
Tippre azért, mert a char* meg a string az nem ekvivalens. Ld. a fentebb linkelt dokumentációt.
- A hozzászóláshoz be kell jelentkezni
Ha minden kötél szakad, rakd körbe egy C kóddal, ami indít egy socket-et, aztán azon keresztül kommunikálj.
- A hozzászóláshoz be kell jelentkezni
Nem igazán értem, mire gondolsz, ki tudnád fejteni?
- A hozzászóláshoz be kell jelentkezni
Irnék egy C kódot, ami
- használja a DLL-t, és
- nyit egy TCP socket-et (HTTP) / vagy valamilyen IPC megoldást
- megvárja, amíg valaki csatlakozik
- tud üzenetet fogadni
- a kapott üzenetből kiszedi az paramétereket
- meghívja a függvényt
- az eredményt visszaadja a hívó félnek
Már nyilván akkor, hogy ha ez megvalósítható a rendszerben.
https://stackoverflow.com/questions/2064103/interprocess-communication-…
- A hozzászóláshoz be kell jelentkezni
szent szar...
--
GPLv3-as hozzászólás.
- A hozzászóláshoz be kell jelentkezni
No plz...
Erre van a C++/CLR. Pont ilyen ragasztási dolgokra találták ki. Az, amit te javasolsz az a taknyolás magasfoka.
- A hozzászóláshoz be kell jelentkezni
Sikerült megoldani?
Depends.exe mit mond rá?
Ha átküldhető privátban, rá tudok nézni.
- A hozzászóláshoz be kell jelentkezni