我有一个我需要在Python中实现的纯虚拟类,所以它是从C ++框架中调用的。
档案example.h
:
/** Abstract reader to be implemented */
class Reader {
public:
/// Read maximum of `n` bytes into `c`
virtual int read(char *c, int n) = 0;
virtual ~Reader() {}
};
void test(Reader &r);
档案example.cpp
#include "example.h"
void test(Reader &r) {
char buf[] = {0, 0, 0};
r.read(buf, 3);
}
SWIG界面:
%module(directors="1") example
%{
#include "example.h"
%}
%feature("director") Reader;
%include "example.h"
Python测试代码:
import example
class ReaderImpl(example.Reader):
def __init__(self):
example.Reader.__init__(self)
def read(self, c, n):
''' Demo impl '''
print type(c)
return 0
example.test(ReaderImpl())
后者将打印<type 'str'>
这对我没用,因为我应该写入缓冲区。所以,问题是:有没有办法告诉SWIG我宁愿为char *
写一些东西,也许像ctypes数组一样?
答案 0 :(得分:3)
查看http://www.swig.org/Doc1.3/Python.html#Python_nn48
中的31.7.4 String handling
部分
改变并不是那么简单,因为字符串的长度可以改变。如果你真的想要一个数组或类似的东西,请查看有关如何定义自己的类型映射的文档。
考虑到python映射的开销,只需从read()
返回一个字符串就可能会更好(更简单的代码)。
答案 1 :(得分:1)
我通过类型映射解决了这个问题:
%typemap(directorin) char * {
$input = PyInt_FromLong((unsigned long)$1;
}
结果,实现将接收一个整数,可以将其转换为ctypes指针:
from ctypes import cast, c_char, POINTER
class ReaderImpl(example.Reader):
def read(self, buf, n):
ptr = cast(buf, POINTER(c_char))
# populate ptr[0]...ptr[n-1]
另一种选择是从Reader
继承一个中间类,并根据返回字符串的纯虚方法实现read
。这个新方法将在Python中实现。