[Megoldhatatlan] MSVC dll + MinGW, C++

 ( tr3w | 2008. június 6., péntek - 12:04 )

Sziasztok!

Adva van egy MSVC-vel (8.0) fordított dll, a hozzá való .lib, és .h fájlokkkal. Ezt szeretném használni egy mingw-s programból.

Ez alapján csináltam .a fájlt.

Ha a .h fájlokban az osztályoknál van __declspec(dllimport), akkor ilyeneket kapok:

surfdetector.cpp:53: undefined reference to `_imp___ZN4surf5ImageC1EPS0_b'

Ha nincs, akkor ilyeneket:

surfdetector.cpp:53: undefined reference to `surf::Image::Image(surf::Image*, bool)'

A dll-ben ilyen tuti van (méghozzá __thiscall előtaggal, bármi is ez)...

Ötlet?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

A "surfdetector.cpp:53: undefined reference to ..." üzenet azt jelenti, hogy a .cpp 53. sorában hivatkozol valamire, amihez nincs definíció, vagyis itt még nem jutott el odáig, hogy a .dll-t vizsgálná.
A hibát a .h fájlban keresd!

"undefined reference is a linker error. It's not a compile error. #includes don't help. You did not define the thing in the error message, or you forgot to link the file that defines it, or you forgot to link to the library that defines it, or if its a static library you have the wrong order. Check which one. (Note that on some compilers it's called unresolved external)"

1500%, hogy linkelési időben történik...

Illetve az is biztos, hogy -lakarmi is ott van és libakarmi.a fájl is van, és meg is találja.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Akkor az lesz a probléma, hogy a C++ fordító a neveket a függvény tipusától függően kiegészíti, és a kiegészítés szabályai az MSVC és a MINGW esetén eltérnek.
A megoldás az lehet, hogy megnézed a tényleges függvény neveket a könyvtárakban és futásidőben töltöd be a dll-t (LoadLibrary) és a függvényeket(GetProcAddress).

Ezzel az a gond, hogy ez egy C++-os lib, és nincs felkészítve ilyen használatra, tehát nincs factrory fv...

Azaz egyenként kéne a tagfv-ek címeit lekérnem, beállítanom, ami macerás, illetve most hirtelen nem is látom, hogy a konstruktorok esetében ez működne-e...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

"Akkor az lesz a probléma, hogy a C++ fordító a neveket a függvény tipusától függően kiegészíti, és a kiegészítés szabályai az MSVC és a MINGW esetén eltérnek."

Reméltem, hogy csak ez a külömbség, és ez valami ügyes tool-lal megoldható. A mingw faq is erre engedett következtetni.

Most viszont ott tartok, hogy a .def fájlban kézzel felvettem a mingw által keresett neveket mint aliast. Ebből .a fájlt generálva a program lefordult, majd azonnal elhalt... Valószínűleg komolyabb különbség van.

Gyanum szerint a gondot a thiscall hívás okozza, és nekem úgy tűnik, mingw alatt nincs lehetőség a msvc-féle működésre...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

up

Pontosan milyen fordítási parancsot is használsz?
Használod-e a -L... kapcsolót a lib elérhetőségének megadására?

surfWINDLL.dll a dll neve, használom a -L-t a könyvtármegadáshoz, illetveilletve -lsurfWINDLL-t a lib-hez.
A libet megtalálja, ha hülyeséget írok, rögtön sikít...

Elméletileg a MinGW -lakarmi esetén először libakarmi.a-t keres, majd akarmi.dll, tehát ez se lehet gond...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Elméletileg a MinGW -lakarmi esetén először libakarmi.a-t keres, majd akarmi.dll, tehát ez se lehet gond...

Ez nem MinGW specialitas, hanem W32 okorseg. DLL-t direktbe nem lehet linkelni, kell hozza egy imp lib, hogy tudja a linker mit kell osszecuccolni. Ezt az export file-bol a dllwrap/dlltool parossal lehet generalni. Az export file-t pedig nm-bol egy perl scriptel. Ez megtalalhato a mingw.org-on (is).

---
pontscho / fresh!mindworkz

Valójában de: lásd itt
"direct linking to a dll" részben
"Linking directly to a dll without using the import library can be done two ways:"

Egyébként nyilván ez se csinál mást, mint a scriptes, dlltool-os megoldás.

De ha elolvasod a topic többi résztét rájössz, hogy messze nem itt a gond...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Jah, lattam, csak nem egeszseges az a feature. Viszont a dll az "sajat" cucc, vagy egyaltalan nincs lehetoseg egy-ket modositast kerni?

---
pontscho / fresh!mindworkz

Nem, nem saját, és nem lehet módosítást kérni.

Az ő nézőpontjukból mindent megtettek, hiszen van msvc 7-es, msvc 8-as verzió is, sőt van egy Linuxos gcc-s.

Az már az én hülyeségem, hogy win alatt mingw-vel akarom használni... :)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

>> DLL-t direktbe nem lehet linkelni, kell hozza egy imp lib, hogy tudja a linker mit kell osszecuccolni.

nem

ok

---
pontscho / fresh!mindworkz

Köszi mindenkinek, a probléma megoldhatalan, legalábbis így.
A c++ elnevezések kódolása még véletlenül sem egyforma, ugyanis nincs ilyen a szabványban. Hasonlóan a hívási módok is különböznek.

Win alatt van szabvány (COM) amivel virtuális osztályok esetében megoldható, de ott sem egyszerű, eleve úgy kell tervezni az osztályt.

Esetemben csak az működne, ha Visual C++-ban írnék egy wrapper dll-t, ami vagy tisztán C fv-ekkel, vagy COM-on keresztül csatlakozik a külvilághoz. Természetesen se kivétel, se STL, sőt a structokkal is vigyázni kell...
Inkább hagyom az egészet...

Ha valakit érdekel részletesebben:
http://aegisknight.org/cppinterface.html

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Kedves tr3w.

Ajanlom az extern "C" {} kiprobalasat, a Stroustup (??) konyvbe is ez az ajanlas (ha jol emlexem).

Pl.:

#ifdef __cplusplus
extern "C" {
#endif
void doSomeThing(string stuff);
#ifdef __cplusplus
}
#endif

Vagy

extern "C" void doSomeThing(string stuff);

Az extern "C" ugyanis azt jelenti, hogy C stilusu fuggvenynev generalast szeretnel.

Ketto dolog nem megengedett:
- classokon beluli fuggvenyek extern -elese
- overloadolt fuggvenyek 1-nel tobb valtozatanak extern-elese.

illetve void doSomeThing előtt __declspec(dll*) __stdcall/más linkagetype

Látom write only. :)

Tehát mint írtam, a dll-t amit használni szeretnék, nem én írtam, tehát nem tudom módosítani, sem hogy extern "C"-vel, sem még __stdcall-lal.

A dll-ben pár teljesen közönséges class van, olyan formában, ahogy az msvc kiköpi, ha kap egy __dllspec(dllexport)-ot.

Írhatnék köré egy C-s wrappert, de ez most elmarad...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Szia, ha még aktuális.
MSVC lib-et nem tudsz megetetni gcc-vel csak MS cl-el. Szerintem. Nekem nem jött össze.
Én azt csináltam, hogy LoadLibrary-val betöltöttem a dll-t, így nem kell sem .lib sem .h.
Mondjuk én tudtam, hogy mi van a dll-ben, de ez számodra is kiderül a .h-ból.
Szóval így kaptam egy handle-t a dll-re azt egy GetProcAddress(kapott_handle, "Függvény neve a .h szerint");
visszaadott egy pointer-t, amit ha a megfelelő függvény pointer kapott meg, akkor már meg
is tudtam hívni, és működik a mai napig.
Szerintem.

--
"Megtanultam a zenét, de nem csináltam, s azóta tudással, de irigység nélkül hallgatom.
Megtanultam egy sereg tudományt, mesterséget és művészetet, értek hozzájuk, de nem csinálom, s így érdektelenül tudom azokat élvezni. "
Hamvas Béla

Meg tudja etetni, van valami konverzio a .lib - .a iranyra. Ra kell keresni, mar en sem emlexem.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

A dll, és a lib C++, ezért a normál konverzió nem ér semmit. (Felesleges is, mert a mingw megeszi a C-s .lib-et gond nélkül.)

Elméletileg lehetne írni olyan konvertálót, ami egy rövid kódot a hívás elé rak, és megoldja az eltérő paraméterátadást, stb-t, de ilyen nem létezik.

(Mondjuk a kivételkezelés, meg az stl-es paraméterek átadása, plusz egy csomó minden nem működne, így nem sok értelme lenne egy ilyennek...)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

GetProcAddress nem jó, mert ez egy C++-os lib...

Mindenféle .def fileokkal lehet trükközni, de szart se ér, mert a gcc-nél és az msvc-nél c++ esetében még a paraméterátadási konvenciók sem egyeznek...

Úgyhogy bukta...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Hát nem biztos, hogy ez értelmes lesz itt, de sebaj.

http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Interoperation.html

On many platforms, GCC supports a different ABI for C++ than do other compilers, so the object files compiled by GCC cannot be used with object files generated by another C++ compiler.

An area where the difference is most apparent is name mangling. The use of different name mangling is intentional, to protect you from more subtle problems. Compilers differ as to many internal details of C++ implementation, including: how class instances are laid out, how multiple inheritance is implemented, and how virtual function calls are handled. If the name encoding were made the same, your programs would link against libraries provided from other compilers—but the programs would then crash when run. Incompatible libraries are then detected at link time, rather than at run time.

Igen pont ez volt a probléma...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o