Shared library Nutzung in python "undefined symbol"?

2 Antworten

Wie schon gesagt ist Dein Problem das Name Mangling

Du könntest jetzt natürlich mal versuchen den gemangelten Namen zu nutzen, Problem: Das Mangling hat in der Regel keine stabile ABI.

Du könntest mit

extern C

arbeiten, Dein PRoblem ist aber, daß Du kein instanziiertes Objekt hast, auf dessen Methoden Du arbeiten könntest.

Ich würde ja mal nach Docs zum Thema C++ DSO und Python schauen, ich vermute Du wirst nicht um ein extern C Interface mit static storage einer Schnittstellenklasse herumkommen - aber ich mag mich irren.

hiwhatsup22 
Fragesteller
 10.04.2023, 18:25

Ist meine Herangehensweise richtig? Ich versuche nun die Funktionen die in der cpp implementiert wurden zu ändern. ZB extern "C" __attribute__((visibility("default"))) void det(int argc, char **argv) { .... ich möchte auf diese Methode der lib von außen zugreifen. Scheinbar reicht das noch nicht denn ich sehe nach der Kompilierung der cpp Datei in ein .so über nm -D mylib.so" immer noch keine "det" methode. Im Makefile erstelle ich die .so über : ocr_db_crnn: fetch_clipper fetch_opencv crnn_process.o db_post_process.o clipper.o cls_process.o

   $(CC) -shared $(SYSROOT_LINK) $(CXXFLAGS_LINK) crnn_process.o db_post_process.o clipper.o cls_process.o -o libocr_db_crnn.so $(CXX_LIBS) $(LDFLAGS)

0
KarlRanseierIII  10.04.2023, 20:14
@hiwhatsup22

Schaue Dir einfach mal:

https://isocpp.org/wiki/faq/mixing-c-and-cpp#call-cpp

an. Im Endeffekt erwartet Python ja ne C Linkage. Wenn Du wirklich mit Klassen arbeiten möchtest, dann wirst Du um einen Wrapper nicht herumkommen.

Ich hatte ursprünglich angenommen (oder eher gehofft), daß es mit statischen Membern einfacher ist und Du einfach eine Wrapperklase nehmen könntest. Aber nein, geht wohl doch nicht :-/.

Das Beispiel geht davon aus, daß Du anderweitig instanziierst. Hier böte sich ggf. der Zeitpunkt das Ladens des Moduls an, um das zu erledigen.

Und ja, es wird definitiv unschön.

0
hiwhatsup22 
Fragesteller
 10.04.2023, 20:29
@KarlRanseierIII

Das verstehe ich nicht so ganz. Also am einfachsten möchte ich erstmal dem ganzen cpp code der bereits existiert meine eigene function hinzufügen die erstmal nut 5 zurückgibt, nur um es zu testen. Dann füge ich also direkt zB über der main() meinen Code ein?

extern "C" int run_program() {
  return 5;
}

Wenn ich das jetzt als shared library kompiliere sehe ich über nm -D leider wieder keine Funktion die so heißt. Also irgendwas fehlt noch.

0
KarlRanseierIII  10.04.2023, 20:51
@hiwhatsup22

Ich habe das gerade mal mit

g++ -fPIC -shared -Wl,-soname dummy.so.1 -o dummy.so  dummy.cc

durch g++ gejagt und less meint:

[...]
Symbol table '.dynsym' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     5: 00000000000010f5    11 FUNC    GLOBAL DEFAULT   10 run_program

Das sieht aus, als wäre kein Mangling gemacht worden.

0
hiwhatsup22 
Fragesteller
 10.04.2023, 21:07
@KarlRanseierIII

ich versuche es dann lieber auch erstmal an einem testprojekt. Melde mich dann sobald es geklappt hat.

0
hiwhatsup22 
Fragesteller
 10.04.2023, 21:20
@KarlRanseierIII

Tatsächlich funktioniert alles ohne Probleme. Hm. Dann muss es ja scheinbar am makefile liegen, ich nutze dort folgenden Befehl um die .so zu erstellen:

ocr_db_crnn: fetch_clipper fetch_opencv crnn_process.o db_post_process.o clipper.o cls_process.o
   $(CC) -shared $(SYSROOT_LINK) $(CXXFLAGS_LINK) crnn_process.o db_post_process.o clipper.o cls_process.o -o libocr_db_crnn.so $(CXX_LIBS) $(LDFLAGS)

Leider habe ich nur sehr wenig Erfahrung in sowas, wie müsste ich die Flags anpassen/welche hinzufügen um die selbe Funktionalität wie bei

g++ -fPIC -shared -Wl,-soname dummy.so.1 -o dummy.so  dummy.cc

zu erreichen?

0
KarlRanseierIII  10.04.2023, 21:47
@hiwhatsup22

Das mit dem soname kann erstmal entfallen, das wird eh nur an den Linker durchgeeicht, damit ein soname Symbol vorhanden ist - kannste zu einem 'will do later' machen (JE nachdem was Python da erwartet).

Sollte es nicht eher $(CXX) sein?

Wo definierst Du denn die anderen Variablen?

0
hiwhatsup22 
Fragesteller
 10.04.2023, 21:51
@KarlRanseierIII

Ich hab es tatsächlich durch ausprobieren hinbekommen. Einfach die Flags

-fPIC -shared -Wl

hinter das $(CC) . Hab eben nachgelesen, dass es nur Formsache ist ob man CC oder CXX schreibt. Angeblich nutzt der linker bei beidem die gleiche Referenz. Sagt mir jetzt nicht viel aber scheint wohl so zu funktionieren.

nm -D libocr_db_crnn.so' | grep run
00000000000a50b8 T run_program

Vielen Dank soweit, das bringt mich schonmal sehr viel weiter!

0
KarlRanseierIII  10.04.2023, 22:07
@hiwhatsup22

Ah okay. Ich sags mal so, man hat es nicht immer alles im Kopf :-D.

Und:

Bitte, gern geschehen, gut wenn es Dich schonmal weiter gebracht hat. Manchmal hat man bei so Dingen echt zu kämpfen ;-).

0

Schau Dir mal die Symbole an, die die shared Library exportiert. Ich würde wetten, dass add nicht dabei ist.

C++ macht normalerweise Name Mangling, d.h. Die Namen werden umgesetzt um z.B. verschiedene Typen von Eingangsparametern umzusetzen. Add könnte ja eine Funktion von void add(void), von int add(int) und von add(const string&) String sein. Dieses müsste der Linker wissen, um calls zur entsprechenden Funktion linken zu können. Darum gibt es Name Mangling.

hiwhatsup22 
Fragesteller
 09.04.2023, 11:29

nm -D libcalc.so w __cxa_finalize w __gmon_start__ w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 00000000000010fa T _ZN4Calc3addEv

Hab gegoogelt, T steht wie du sagst für name mangling und _ZN4Calc3addEv müsste dann die add function sein. Also wird sie ja scheinbar doch exportiert? Und was genau muss ich dann im linker angeben damit ich sie als "lib.add" in python nutzen kann?

0
W00dp3ckr  09.04.2023, 11:31
@hiwhatsup22

Ja, aber nicht zwingend unter dem Namen, den Python erwartet, kann das sein?

Wenn ich Dir sage, ich suche nach “calc” und Du mir sagst: “hallo, ich habe da _ZN4Calc3adEv, das ist doch das gleiche”, dann führt das zu Heiterkeit im richtigen Leben. Du musst schauen, ob Python C++ oder C export erwartet.

1
hiwhatsup22 
Fragesteller
 09.04.2023, 11:40
@W00dp3ckr

Tatsächlich.. ich muss einfach 1zu1 den mangled name verwenden und dann funktioniert auch schon alles ohne Probleme! Vielen vielen Dank dir für den Tipp!

0
W00dp3ckr  09.04.2023, 11:59
@hiwhatsup22

Super! Du kannst das Mangling auch abstellen, d.h. Dem C++ sagen, dass es den C-Namen verwenden soll für einige Methoden. Wie das geht, weiß ich nicht mehr.

0