- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是我想要做的一个简化示例。假设我在 test.h 中有以下 C++ 代码
double f(double x);
double myfun(double (*f)(double x));
import test
f = test.f
myfun(f)
TypeError: in method 'myfun', argument 1 of type 'double (*)(double)'
%typemap double f(double);
最佳答案
注意:这个答案有很长的部分是关于变通方法的。如果您只是想使用此方法,请直接跳至解决方案 5。
问题
您已经遇到了这样一个事实,即在 Python 中一切都是对象。在我们考虑修复问题之前,首先让我们了解正在发生的事情。我已经创建了一个完整的示例来使用头文件:
double f(double x) {
return x*x;
}
double myfun(double (*f)(double x)) {
fprintf(stdout, "%g\n", f(2.0));
return -1.0;
}
typedef double (*fptr_t)(double);
fptr_t make_fptr() {
return f;
}
make_fptr()
返回一些东西给 Python 的函数我们知道将被包装成一个函数指针。
%module test
%{
#include "test.h"
%}
%include "test.h"
swig2.0 -Wall -python test.i && gcc -Wall -Wextra -I/usr/include/python2.6 -std=gnu99 -shared -o _test.so test_wrap.c
test.f
的类型和调用结果的类型
test.make_fptr())
:
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> type(test.f)
<type 'builtin_function_or_method'>
>>> repr(test.f)
'<built-in function f>'
>>> type(test.make_fptr())
<type 'SwigPyObject'>
>>> repr(test.make_fptr())
"<Swig Object of type 'fptr_t' at 0xf7428530>"
myfun(test.f)
不会工作。
test.make_fptr()
返回一个指向函数指针的 Python 句柄
f
.所以我们实际上可以调用:
f=test.make_fptr()
test.myfun(f)
%constant
. (通常这用于公开编译时常量,但本质上所有函数指针实际上都是最简单的形式)。
%module test
%{
#include "test.h"
%}
%constant double f(double);
%ignore f;
%include "test.h"
%constant
指令告诉 SWIG 包装
f
作为函数指针,而不是函数。
%ignore
需要避免有关看到同一标识符的多个版本的警告。
typedef
和
make_fptr()
函数)
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> type(test.f)
<type 'SwigPyObject'>
>>> repr(test.f)
"<Swig Object of type 'double (*)(double)' at 0xf7397650>"
>>> test.f(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'SwigPyObject' object is not callable
test.f
从 Python 方面。这导致了下一个解决方案:
test.f
作为函数指针和内置函数。我们可以通过简单地使用
%rename
来做到这一点。而不是
%ignore
:
%{
#include "test.h"
%}
%constant double f(double);
%rename(f_call) f;
%include "test.h"
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> repr(test.f)
"<Swig Object of type 'double (*)(double)' at 0xf73de650>"
>>> repr(test.f_call)
'<built-in function f_call>'
test.f_call
的想法。或只是
test.f
取决于我想处理的上下文
f
当时。我们可以通过在 SWIG 接口(interface)中编写一些 Python 代码来实现这一点:
%module test
%{
#include "test.h"
%}
%rename(_f_ptr) f;
%constant double f(double);
%rename(_f_call) f;
%feature("pythonprepend") myfun %{
args = f.modify(args)
%}
%include "test.h"
%pythoncode %{
class f_wrapper(object):
def __init__(self, fcall, fptr):
self.fptr = fptr
self.fcall = fcall
def __call__(self,*args):
return self.fcall(*args)
def modify(self, t):
return tuple([x.fptr if isinstance(x,self.__class__) else x for x in t])
f = f_wrapper(_f_call, _f_ptr)
%}
test.f
成为这个包装器的一个实例。当它作为函数被调用时,它会传递调用。最后我们在
myfun
中插入一些额外的代码包装器来交换真正的函数指针而不是我们的包装器,注意不要改变任何其他参数(如果有的话)。
import test
print "As a callable"
test.f(2.0)
print "As a function pointer"
test.myfun(test.f)
%rename
,
%constant
和包装器实例创建,但我们无法真正摆脱使用
%feature("pythonprepend")
的需要我们到处将这些包装器传回 SWIG。 (如果可以透明地做到这一点,这远远超出了我的 Python 知识)。
swig -python -builtin
它根本行不通,因为首先没有要添加 Python 代码! (您需要将包装器的构造更改为:
f = f_wrapper(_test._f_call, _test._f_ptr)
,但这还不够)。
%module test
%{
#include "test.h"
%}
%{
static __thread PyObject *callback;
static double dispatcher(double d) {
PyObject *result = PyObject_CallFunctionObjArgs(callback, PyFloat_FromDouble(d), NULL);
const double ret = PyFloat_AsDouble(result);
Py_DECREF(result);
return ret;
}
%}
%typemap(in) double(*)(double) {
if (!PyCallable_Check($input)) SWIG_fail;
$1 = dispatcher;
callback = $input;
}
%include "test.h"
void*
用户数据参数以及回调的实际输入。在这些情况下,“userdata”可以是 Python 可调用的。
PyObject
向后工作并尝试找出它是哪个函数(如果有)的包装器:
%module test
%{
#include "test.h"
%}
%{
static __thread PyObject *callback;
static double dispatcher(double d) {
PyObject *result = PyObject_CallFunctionObjArgs(callback, PyFloat_FromDouble(d), NULL);
const double ret = PyFloat_AsDouble(result);
Py_DECREF(result);
return ret;
}
SWIGINTERN PyObject *_wrap_f(PyObject *self, PyObject *args);
double (*lookup_method(PyObject *m))(double) {
if (!PyCFunction_Check(m)) return NULL;
PyCFunctionObject *mo = (PyCFunctionObject*)m;
if (mo->m_ml->ml_meth == _wrap_f)
return f;
return NULL;
}
%}
%typemap(in) double(*)(double) {
if (!PyCallable_Check($input)) SWIG_fail;
$1 = lookup_method($input);
if (!$1) {
$1 = dispatcher;
callback = $input;
}
}
%include "test.h"
%typemap(constcode)
允许
%constant
用作方法和函数指针。事实证明,SWIG 已经支持这样做,这是我在阅读一些 SWIG 源代码时发现的。所以实际上我们需要做的很简单:
%module test
%{
#include "test.h"
%}
%pythoncallback;
double f(double);
%nopythoncallback;
%ignore f;
%include "test.h"
%pythoncallback
启用一些全局状态,导致后续函数被包装为可用于函数指针和函数!
%nopythoncallback
禁用那个。
-builtin
):
import test
test.f(2.0)
test.myfun(test.f)
%pythoncallback
.所以前四种解决方案大多只是作为定制 SWIG 接口(interface)的示例有用。
关于python - 如何使用 SWIG 包装在 python 中接收函数指针的 C++ 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22923696/
我正在制作一个 C++ 库的包装器,以便它可以从 Java 中使用,我正在用 Swig 做这个。 我面临的是我有一个类(class) SomeClass ,它有一些重载的方法( someMethod
我有许多要在 SWIG 中重命名的类。我的大部分类(class)看起来像这样some_class ,我想将其重命名为 SomeClass .这很简单: %replace("%(camelcase)s"
PyPy 有一些 compatibility limitations ,尤其是关于 CPython C API。 我用 QuickFix预编译的 SWIG 绑定(bind)附带的包,我正在考虑将它与
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
使用 SWIG 生成接口(interface)模块时,生成的 C/C++ 文件包含大量静态样板函数。因此,如果想通过在同一个应用程序中使用许多单独编译的小接口(interface)来模块化 SWIG
我正在应用 SWIG 手册中有关嵌套类的解决方法,该部分使用全局内部类。在这里,我将向您展示一个类似于手册中的版本,但为您尽可能地简化了。我还必须将内联定义 {} 添加到 method(),因为没有它
我有一个现有的库 (JPhysX),它是原生 C++ 库 (PhysX) 的 Java 包装器。 Java 库使用 SWIG 生成的类型,例如 com.jphysx.SWIGTYPE_p_NxStre
有没有办法动态向下转换 swig 对象的 swig 代理? 这样做的原因是为了模拟 C++ 向下转换,但纯粹来自 python。例如,典型的 C++ 用法是 MyBase* obj = new MyB
我在远程服务器上工作,所以我在本地安装了 swig,使用 -prefix=/home/user/directory。 我有一个来自同事的 makefile,其中包含以下命令: swig $(SWIG_
据我所知,在用于将 c++ 文件编译为 python 扩展模块的 .i 文件中,我们可以添加一些 python 代码,如下所示(来自 example for adding additional pyt
我的 Swig 文件 (.i) 中有以下代码: %extend vgSofa::handler::VertexShape { vgd::Shp createVSWithNode( so
我有一个用 swig 包装的类的 C++ 代码。我无法修改代码或包装。在 python 中,我使用 ctypes 拥有一个指向所述 C++ 类的实例的指针。如何围绕该指针创建一个 swig 包装器?
我开始掌握 SWIG 的窍门,SWIG 的最新版本 (v3.0) 似乎可以处理我开箱即用所需的一切,包括 C++11 功能,但我遇到了麻烦开始在我的导演类(class)中使用 shared_ptr。
我正在使用 javacode 类型映射来添加一些附加函数来代替 SWIG 生成的函数。我想删除 SWIG 为 unsigned char mac[6]; 生成的默认 getter 和 setter(p
我正在使用 SWIG 为我的 C 库生成 Python 语言绑定(bind)。我已经设法构建了绑定(bind)和导出的数据结构,但在使用该库时我不得不跳过一些障碍。 例如,C 头文件的数据类型和函数原
我最近在node-js应用程序中从jade模板引擎切换到了swig。在使用jade时我使用了命令 jade.render('/sample.jade',{obj:object});渲染模板并传递对象。
我在我的 python 代码中发现了瓶颈,尝试了 Psycho 等。然后决定编写一个 c/c++ 扩展来提高性能。 在 swig 的帮助下,您几乎不需要关心参数等。一切正常。 现在我的问题是:swig
由于 SWIG 无法解析 __attribute__((packed))在我想包装的一些 C 结构上,我通过放置一个 #define __attribute__(x) 在我的.i文件。 这什么时候会来
我有一个包含 C++ header 的 SWIG 文件。 痛饮文件: %module my_module %{ #include "my_c_file.h" %} %include "my_c_fil
我正在尝试学习如何使用 SWIG,并且想知道我是否正在执行一些不需要执行的额外步骤。我目前有文件 Dog.cpp、Dog.h 和 Dog.i。我正在尝试使用 SWIG 包装 Dog.cpp 以便在 P
我是一名优秀的程序员,十分优秀!