【问题标题】:ctypes: pass numpy to c++ dllctypes:将 numpy 传递给 c++ dll
【发布时间】:2021-09-28 01:22:04
【问题描述】:

我正在使用 C++ 来实现一个 dll,并使用 python 来使用它。当我将一个 numpy 传递给 dll 时,会报告一个错误

我的 C++ 代码是:

    __declspec(dllexport) void image(float * img, int m, int n)
    {
        for (int i = 0; i < m*n; i++)
        {
            printf("%d ", img[i]);
        }
    }

在上面的代码中,我只是传递了一个numpy,然后打印出来。

那么,我使用这个dll的python代码是:

import ctypes
import numpy as np

lib = ctypes.cdll.LoadLibrary("./bin/Release/dllAPI.dll")

img = np.random.random(size=[3, 3])*10
img = img.astype(np.float)
img_p = img.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
lib.image.argtypes = (ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int)
lib.image.restype = None
print('c++ result is: ')
lib.image(img_p, 3, 3)
print('\n original data is:')
print(img)

打印出来的信息是:

c++ result is: 
-536870912 -1073741824 0 1610612736 -1073741824 1073741824 1610612736 536870912 -2147483648 
 original data is:
[[7.76128455 3.16101652 7.44757958]
 [2.32058998 9.96955139 3.26344099]
 [9.42976627 1.34360611 8.4006054 ]]

我的 C++ 代码打印了一个随机数,看起来内存泄漏了。

我的环境是:

win 10
vs 2015 x64
python 3.7
ctypes 1.1.0

如何通过ctypes 将 numpy 传递给 C++?任何建议都值得赞赏~~~

------------------更新----------

C++ 代码对printf 有一个错误,我将 C++ 代码更新为:


    __declspec(dllexport) void image(float * img, int m, int n)
    {
        for (int i = 0; i < m*n; i++)
        {
            printf("%f ", img[i]);
        }
    }

但是,打印出来的信息还是不正确的:

c++ result is: 
12425670907412733350375273403699429376.000000 2.468873 0.000000 2.502769 4435260031901892608.000000 2.458449 -0.000000 2.416936 -4312230798506823897841664.000000 
 original data is:
[[7.50196262 8.08859399 7.33518741]
 [6.67098506 0.04736352 9.5017838 ]
 [3.47544102 9.09726041 0.48091646]]

【问题讨论】:

  • 浮点打印需要%f,否则内存将被解释为int而不进行强制转换。 (测试表明double a = 2.5 打印为-1439846888)。编译器应该已经警告过你了。如果要四舍五入,请尝试投射到 int
  • 感谢您的回复。我已经更正了我的 C++ 代码。而且打印出来的信息还是不正确的。

标签: python c++ numpy ctypes


【解决方案1】:

所以经过一番挖掘,我发现显然numpy.float,实际上等同于ctypes.c_double(?),你应该这样做img.astype(ctypes.c_float),这样指针就指向了有效的结果。我不知道为什么 np.float 会是 64 位浮点数,但从我的调试中我看到了。如果你想重现这个尝试在 python 中打印img_p[0] 来查看。

注意:在这种情况下,使用特定的强制转换可能是最佳实践,因为可能会定义不同的 dtype 实现,从而导致这个确切的错误(即使两者都是 float

【讨论】:

  • 非常感谢。是numpy.float 造成了这个错误。我把img = img.astype(ctypes.c_float)换成img = img.astype(np.float32),结果是正确的。另外,我们如何调试dll?我的流程是:用debug运行python代码,在lib.image(img_p, 3, 3)之前设置断点;然后,我将 vs 附加到 pycharm64.exe 进程。但是,我发现我仍然无法输入 C++ 代码。你有什么建议吗?
  • @QiangZhang 您可以尝试从使用它的c++ 程序调试它。您也可以尝试将asm(".byte 0xcc"); 放在函数的开头。这应该可以控制您正在使用的调试器(如果我没记错的话,它是 x86-64/x86 上的 int3(breakpoint) 指令)。老实说,我以前从未在 python 代码上使用过调试器,尤其是ctypes。注意:我认为trap,如果我没记错的话(或者在 linux 上确实如此),如果没有附加调试器,程序就会崩溃
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-15
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多