2015-06-22 33 views
5

Mam proste funkcję testową C++:ctypes błąd AttributeError symbol nie zostanie znaleziony, OS X 10.7.5

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <locale.h> 
#include <wchar.h> 

char fun() { 
    printf("%i", 12); 

    return 'y'; 
} 

kompilacji:

gcc -o test.so -shared -fPIC test.cpp 

i używanie go w Pythonie z ctypes:

from ctypes import cdll 
from ctypes import c_char_p 

lib = cdll.LoadLibrary('test.so') 
hello = lib.fun 
hello.restype = c_char_p 

print('res', hello()) 

ale wtedy pojawia się błąd:

Traceback (most recent call last): File "./sort_c.py", line 10, in <module> 
    hello = lib.fun File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 366, in __getattr__ 
    func = self.__getitem__(name) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 371, in __getitem__ 
    func = self._FuncPtr((name_or_ordinal, self)) 
AttributeError: dlsym(0x100979b40, fun): symbol not found 

Gdzie jest problem?

używając:

Mac Os X 10.7.5 and Python 2.7

Odpowiedz

8

Pierwszym problemem jest to C++ nazwa przekręcona. Jeśli prowadzisz nm na pliku .so dostaniesz coś takiego:

nm test.so 
0000000000000f40 T __Z3funv 
       U _printf 
       U dyld_stub_binder 

jeśli oznaczyć go jako stylu C podczas skompilowane z C++:

#ifdef __cplusplus 
extern "C" char fun() 
#else 
char fun(void) 
#endif 
{ 
    printf("%i", 12); 

    return 'y'; 
} 

nm daje:

0000000000000f40 T _fun 
       U _printf 
       U dyld_stub_binder 

Twój drugi problem polega na tym, że pyton umrze z Segmentation fault: 11 (na OS X). C++ zwraca char, podczas gdy zaznaczasz go w pythonie jako wskaźnik do znaku. Użyj:

hello.restype = c_char 

zamiast tego (zmień oświadczenie import w celu dopasowania).

EDYCJA: jak @eryksun zauważył, nie powinieneś używać gcc, powinieneś zamiast tego użyć g++. W przeciwnym razie poprawne środowisko wykonawcze C++ nie będzie połączone. Aby sprawdzić OS X:

otool -L test.so 

(ldd, narzędzie zwykle używany w systemie UNIX/Linux, nie jest rozprowadzany z OS X)

+1

Czy używając 'gcc' powiązać program w C++ do prawidłowego C++ Runtime w systemie operacyjnym X? Spodziewam się, że wymaga 'g ++'. Wiem, że to nie ma znaczenia w tym przypadku, ponieważ kod przykładowy używa właśnie standardowych funkcji biblioteki C. – eryksun

+0

@eryksun: 'gcc' kompiluje go jako C++, jeśli plik źródłowy ma przyrostek' .cpp', ale masz rację, preferowane jest 'g ++'. Nie wspomniałem o tym w mojej odpowiedzi, ponieważ był tam komentarz (twój?). Jest to w oczywisty sposób C++, ponieważ wymieszanie nazw różni się od warunkowego "zewnętrznego" C "(patrz treść wpisu). – cdarke

+1

'gcc' kompiluje źródło jako C++, ale w Linuksie nie łączy się z libstdC++. So.6, więc ładowanie biblioteki kończy się niepowodzeniem, jeśli wymaga biblioteki C++. – eryksun