我有private.h
,public.h
和file.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 <assert.h>
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 <stdlib.h>
#include <string.h>
#include <assert.h>
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中给了我很多错误。 我该如何解决这个问题?
答案 0 :(得分:7)
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)
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
)
import pyximport; pyximport.install()
from person import Person
p = Person('Garry')
print p.name
$ python test_person.py
Garry
答案 1 :(得分:1)
一般来说,除非你有一些非常特殊的要求,否则手工做这种事是没有意义的。相反,使用SWIG为您生成包装器。你不需要努力使这些细节正确,并且当C代码改变时作为奖励,重新生成新的包装器以匹配它是微不足道的。