python 调用 C++的DLL,函数参数是数组怎么处理?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 调用 C++的DLL,函数参数是数组怎么处理?相关的知识,希望对你有一定的参考价值。
最近刚学会用boost.python调用简单的c的函数,但是需要处理的是C++的类,我可以麻烦点把C++类都转化成C语言函数,但是函数参数有数组的怎么办?可以用C++的VECTOR吗,python怎么传入VECTOR?
好吧,想到个土办法,就是DLL里设个全局数组,python的数组用个循环,将数组的值一个个赋值给DLL里的全局变量。。
给你一个例子看看,你就知道怎么做了
C++的接口
typedef structunsigned long DeviceType;
int Handle;
int NumberOfClients;
int SerialNumber;
int MaxAllowedClients;
NeoDevice;
int _stdcall icsneoFindNeoDevices(unsigned long DeviceTypes, NeoDevice *pNeoDevices, int *pNumberOfDevices);
Python调用的代码:
class NeoDevice(Structure):_fields_ = [("DeviceType",c_ulong),
("Handle",c_int),
("NumberOfClients",c_int),
("SerialNumber",c_int),
("MaxAllowedClients",c_int)]
class cNeoVICan(CCanBase):
def __init__(self):
neoVi = windll.icsneo40
self.icsneoFindNeoDevices = neoVi.icsneoFindNeoDevices
if __name__ == "__main__":
canBus = cNeoVICan()
print canBus.icsneoGetDLLVersion()
iNumberOfDevices = (NeoDevice * 10)()
num = c_int()
iResult = canBus.icsneoFindNeoDevices(c_ulong(65535), cast(iNumberOfDevices, POINT(NeoDevice)), byref(num)) 参考技术B 你既然都要手动写C了,就在C里转换成PyObject不就行了。
当参数之一是指针数组时,如何从 C# 调用 C++ DLL
【中文标题】当参数之一是指针数组时,如何从 C# 调用 C++ DLL【英文标题】:How to call C++ DLL from C# when one of the parameters is an array of pointers 【发布时间】:2017-11-27 23:32:24 【问题描述】:我有一个 DLL pin C++,它接受两个参数,类似于 C 中的 main() 函数:参数数量,后跟指向各个参数的指针数组:
__declspec(dllexport) void Calculate(int argc, void** argv)
if (argc >= 7)
auto sourceX = *((int*)(argv[0]));
auto sourceY = *((int*)(argv[1]));
auto iterations = *((int*)(argv[2]));
auto resize = *((bool*)(argv[3]));
auto input = (double*)(argv[4]);
auto targetX = *((int*)(argv[5]));
auto targetY = *((int*)(argv[6]));
// Do computations
我能够以这种方式从另一个 C 代码调用导出的函数(在通过 LoadLibrary 和 GetProcAddress 调用加载 DLL 库之后):
int X, Y, iterations;
bool Resize;
double* Input;
// Initialize variables, allocate data for Input
// ...
void* Params[] = &X, &Y, &iterations, &Resize, Input, &X, &Y ;
_Calculate(7, Params);
但是,当我尝试从 C# 调用 DLL 时,它崩溃了。这是我正在使用的 C# sn-p:
[DllImport("computedll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void Calculate(int argc, void** argv);
public void Compute()
int X, Y, iterations;
bool Resize;
double* Input;
// Initialize variables, allocate data for Input
// ...
var Parameters = stackalloc void*[7];
Parameters[0] = &X;
Parameters[1] = &Y;
Parameters[2] = &iterations;
Parameters[3] = &Resize;
Parameters[4] = Input;
Parameters[5] = &X;
Parameters[6] = &Y;
Calculate(7, Parameters);
我在这里做错了什么?有没有办法使这种使用指针数组(void**)的模式起作用?提前致谢。
【问题讨论】:
见:***.com/tags/pinvoke/info 猜测您已经验证了您的 C++ 代码并且您的 C# 代码使用相同的指针大小? 【参考方案1】:构建为 x64,以下工作。这几乎是您的代码。我讨厌在 C/C++ 之外使用 cdecl,所以如果这对你很重要……对不起。重点是...如果您遇到问题,这不是您的实际代码或概念的基础。
Interopy.h:
extern "C"
__declspec(dllexport) void __stdcall Calculate(int argc, void** argv);
来源:
#include "Interopy.h"
void __stdcall Calculate(int argc, void** argv)
if (argc >= 7)
auto sourceX = *((int*)(argv[0]));
auto sourceY = *((int*)(argv[1]));
auto iterations = *((int*)(argv[2]));
auto resize = *((bool*)(argv[3]));
auto input = (double*)(argv[4]);
auto targetX = *((int*)(argv[5]));
auto targetY = *((int*)(argv[6]));
*(int*)argv[5] = 42; //to test
// Do computations
c#(平台目标 x64):
public static class iop
[DllImport("InteropyDll1.dll", CallingConvention = CallingConvention.StdCall)]
unsafe public static extern void Calculate(int argc, void** argv);
unsafe static public void Compute()
int X, Y, iterations;
bool Resize;
double* Input = (double*)IntPtr.Zero;
// Initialize variables, allocate data for Input
// ...
void **Parameters = stackalloc void*[7];
Parameters[0] = &X;
Parameters[1] = &Y;
Parameters[2] = &iterations;
Parameters[3] = &Resize;
Parameters[4] = Input;
Parameters[5] = &X;
Parameters[6] = &Y;
Calculate(7, Parameters);
请注意,此程序集现在依赖于平台。我过去通过多种构建配置解决了这个问题,但我相信还有更好的方法可以解决。无论如何,出于这个原因和其他原因,您都希望将这个不安全的代码放在它自己的程序集中。
【讨论】:
谢谢你!我实施了你的建议,效果很好!我尝试对您的答案进行投票,不幸的是,我的声誉 (6) 还不够。 @StephenDaedalusSepara 不过,您始终可以接受它作为提问者。我相信它旁边有一个复选标记? @StephenDaedalusSepara - 顺便说一句,我不知道这段代码的用途,但如果你要维护它,我会留意 C# 中的Span<T>
和 Memory<T>
7.2.它们专为此类不需要不安全的场景而设计。不过,目前还不错。
(旧版)c++ 代码用于执行在 c# 中不可用或速度较慢的计算。是的,我会维护这些代码一段时间,直到我们得到更好的计算实现。看起来 Span<T>
和 Memory<T>
将成为 c# 的有趣和有用的开发,再次感谢。以上是关于python 调用 C++的DLL,函数参数是数组怎么处理?的主要内容,如果未能解决你的问题,请参考以下文章