我正在为一个使用 SWIG 公开其 C++ API 的程序编写 Python 脚本。 SWIG 公开函数具有如下接口(interface):
void writePixelsRect(JoxColor* colors, int left, int top, int width, int height);
JoxColor 是一个 POD 结构,如下所示:
struct JoxColor {
float r, g, b, a;
};
我可以轻松地在 Python 中创建一个 JoxColor 并像这样调用 writePixelsRect:
c = JoxApi.JoxColor()
c.r = r
c.g = g
c.b = b
c.a = a
JoxApi.writePixelsRect(c, x, y, 1, 1)
用 1x1 像素矩形重复调用 writePixelsRect 非常慢,所以我想从 python 创建一个 JoxColor 数组,这样我就可以写更大的矩形了。这对于 SWIG 类型可能吗?
请注意,我无权访问公开 JoxColor 和 writePixelsRect 的 C++ 库的源代码,因此我无法为此添加帮助功能。我也不想在系统中引入新的 C++ 代码,因为它会迫使我的 python 脚本的用户在他们运行的任何平台上编译 C++ 代码。我确实可以在 python 环境中访问 ctypes,所以如果我能以某种方式将在 ctypes 中创建的 float 组类型转换为 SWIG 的 JoxColor* 类型,它将对我有用。
最佳答案
这有点棘手,但至少对于这部分代码,您可以使用纯 ctypes 解决方案吗?基本上是手动查看共享库文件导出的符号,以找到 writePixelsRect 函数导出的名称。 C++ 会进行名称修改,因此虽然它可能只是 writePixelsRect
如果库作者选择将它设为 extern "C"
,它可能会更困惑一些,例如 _Z15writePixelsRectP8JoxColoriii
(这就是它在我刚刚在我的系统上创建的虚拟 C++ 库中导出的方式)。
在 Linux 上,这个命令应该告诉你符号名称:
nm libjox.so | grep writePixel | cut -d " " -f 3
然后,保存该字符串并将其插入到 Python 代码中,如下所示:
from ctypes import *
LIBRARY_NAME = 'libjox.so'
c = cdll.LoadLibrary(LIBRARY_NAME)
WIDTH = 20
HEIGHT = 20
class JoxColor(Structure):
_fields_ = [("r", c_float), ("g", c_float), ("b", c_float), ("a", c_float)]
ColorBlock = JoxColor * (WIDTH * HEIGHT)
data_array = ColorBlock()
color = JoxColor(0, 0, 1, 0)
for i in range(WIDTH * HEIGHT):
data_array[i] = color
c._Z15writePixelsRectP8JoxColoriiii(data_array, 0, 0, WIDTH, HEIGHT)
假设 _Z15writePixelsRectP8JoxColoriii
是该函数在共享库中可访问的符号。运行这段代码只在我的系统上使用像这样的虚拟库:
#include <stdio.h>
struct JoxColor {
float r, g, b, a;
};
void writePixelsRect(JoxColor *colors, int left, int top, int width, int height) {
int p = 0;
printf("size: %i, %i\n", width, height);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
JoxColor color = colors[p];
printf("pixel: %f, %f, %f, %f\n", color.r, color.g, color.b, color.a);
}
}
}
因此,我希望它离您的环境中的工作代码不远。
关于c++ - 来自 Python 的 SWIG C++ 类型的数组分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5862902/