2015-06-22 23 views
5

Ho una semplice funzione di prova su C++:ctypes simbolo di errore AttributeError non trovato, 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'; 
} 

compilazione:

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

e di utilizzarlo in pitone con 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()) 

ma poi ho un errore:

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 

Dove è un problema?

utilizza:

Mac Os X 10.7.5 and Python 2.7

risposta

8

Il primo problema è C++ nome mangling. Se si esegue nm sul file .so otterrete qualcosa di simile:

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

Se si contrassegna come stile C quando viene compilato con C++:

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

    return 'y'; 
} 

nm dà:

0000000000000f40 T _fun 
       U _printf 
       U dyld_stub_binder 

Il tuo secondo problema è che il pitone morirà con un Segmentation fault: 11 (su OS X). Il C++ sta restituendo un char, mentre lo stai marcando in python come puntatore a un carattere. Usa:

hello.restype = c_char 

invece (alterare la sua dichiarazione import da abbinare).

MODIFICA: come sottolineato da @eryksun, non è necessario utilizzare gcc, è necessario utilizzare g++. In caso contrario, il runtime C++ corretto non sarà collegato. Per controllare OS X:

otool -L test.so 

(ldd, lo strumento normalmente utilizzato su UNIX/Linux, non è distribuito con OS X)

+1

costa usare 'gcc' collegare un programma C++ per il corretto C++ runtime in OS X? Mi aspetterei che richieda 'g ++'. So che non importa in questo caso poiché il codice di esempio utilizza solo le funzioni di libreria standard di C. – eryksun

+0

@eryksun: 'gcc' lo compila come C++ se il file sorgente ha il suffisso' .cpp', ma hai ragione, 'g ++' è preferito. Non l'ho menzionato nella mia risposta perché c'era un commento (il tuo?). È dimostrabilmente C++ perché il nome mangling è diverso con il condizionale "extern" C "' (vedi corpo del post). – cdarke

+1

'gcc' compila il sorgente come C++, ma su Linux non si collega con libstdC++. So.6, quindi il caricamento della libreria fallisce se richiede la lib di C++. – eryksun