包装C库

我有一个private.hpublic.hfile.c ,我需要将它包装到Cython中 。 如何包装函数Person_ptr Person_create(const char* name);

private.h:

 #ifndef __PERSON_PRIVATE_H__ #define __PERSON_PRIVATE_H__ #include "Person.h" typedef struct Person_TAG { char* name; int age; } Person; void person_init(Person_ptr self, const char* name); # endif /* __PERSON_PRIVATE_H__ */ 

public.h

 #ifndef __PERSON_H__ #define __PERSON_H__ #include  typedef struct Person_TAG* Person_ptr; #define PERSON(x) \ ((Person_ptr) (x)) #define PERSON_CHECK_INSTANCE(x) \ assert(PERSON(x) != PERSON(NULL)) /* public interface */ Person_ptr Person_create(const char* name); void Person_destroy(Person_ptr self); const char* Person_get_name(const Person_ptr self); int Person_get_age(const Person_ptr self); void Person_birthday(Person_ptr self); # endif /* __PERSON_H__ */ 

这是file.c

 #include "Person.h" #include "Person_private.h" #include  #include  #include  Person_ptr Person_create(const char* name) { Person_ptr self = PERSON(malloc(sizeof(Person))); PERSON_CHECK_INSTANCE(self); person_init(self, name); return self; } void Person_destroy(Person_ptr self) { PERSON_CHECK_INSTANCE(self); if (NULL != self->name) free(self->name); } /* Do not free not change the returned string! */ const char* Person_get_name(const Person_ptr self) { PERSON_CHECK_INSTANCE(self); return self->name; } int Person_get_age(const Person_ptr self) { PERSON_CHECK_INSTANCE(self); return self->age; } void Person_birthday(Person_ptr self) { PERSON_CHECK_INSTANCE(self); ++self->age; } /* private/protected methods */ void person_init(Person_ptr self, const char* name) { self->name = malloc(sizeof(char) * (strlen(name) + 1)); assert(NULL != self->name); strcpy(self->name, name); self->age = 0; } 

我试图做的是file.pyx:

 from ctypes import * cdef extern from "Person.h": ctypedef struct Person_ptr: pass Person_ptr Person_create "P_create" (char *name) cdef class Person: cdef Person P_create(p_name): return Person_create(p_name) 

它不对 – 它在Cython中编译但是它在GCC中给了我很多错误。 我该如何解决这个问题?

cperson.pxd:

 cdef extern from "Person.h": cdef struct Person_TAG: pass ctypedef Person_TAG* Person_ptr Person_ptr Person_create(char* name) void Person_destroy(Person_ptr self) char* Person_get_name(Person_ptr self) 

person.pyx

 from cperson cimport Person_ptr, Person_create, Person_destroy, Person_get_name cdef class Person: cdef Person_ptr thisptr def __cinit__(self, char* name): self.thisptr = Person_create(name) if self.thisptr is NULL: raise MemoryError def __dealloc__(self): if self.thisptr is not NULL: Person_destroy(self.thisptr) property name: def __get__(self): return Person_get_name(self.thisptr) 

person.pyxbld:

 import os from distutils.extension import Extension dirname = os.path.dirname(__file__) def make_ext(modname, pyxfilename): return Extension(name=modname, sources=[pyxfilename, "Person.c"], include_dirs=[dirname], # or libraries=["person"], if you compile Person.c separately ) 

test_person.py

 import pyximport; pyximport.install() from person import Person p = Person('Garry') print p.name 

 $ python test_person.py Garry 

一般来说,除非你有一些非常特殊的要求,否则手工做这种事是没有意义的。 相反,使用SWIG为您生成包装器。 您不需要努力使这些细节正确,并且作为C代码更改时的奖励,重新生成新的包装器以进行匹配是微不足道的。