包装C库 [英] Wrapping C library

查看:84
本文介绍了包装C库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a private.h, public.h and the file.c, and I need to wrap it into Cython. How do I wrap the function 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:

What I have tried to do is 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错误。
如何解决此问题?

It's not right - it compiles in Cython but then it gives me a lot of errors in GCC. How can I fix this problem?

推荐答案

cperson.pxd:

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:

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



示例



Example

$ python test_person.py 
Garry

这篇关于包装C库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆