使用ctypes模块访问C编写的DLL时出错
我有一个动态链接库(DLL),里面有一个函数,这个函数接收五个双精度浮点数和一个整数:
__declspec(dllexport) struct res ITERATE(double z_r,double z_i,double c_r, double c_i, int iterations, double limit)
它返回一个自定义的结构体,叫做res,这个结构体里面有一个包含三个双精度浮点数的数组:
struct res {
double arr[3];
};
为了返回这些值,我是这样做的:
struct res result; /*earlier in the code */
result.arr[0] = z_real; /*Just three random doubles*/
result.arr[1] = z_imag;
result.arr[2] = value;
return result;
我用MinGW编译了这个库,现在想在Python中使用它,做类似这样的事情:
form ctypes import *
z = [0.0,0.0]
c = [1.0,1.0]
M = 2.0
MiDLL = WinDLL("RECERCATOOLS.dll")
MiDLL.ITERATE.argtypes = [c_double, c_double, c_double, c_double,c_int,c_double]
MiDLL.ITERATE(z[0],z[1],c[0],c[1],100,M) #testing out before assigning the result to anything.
但是,每当我尝试用这些值调用这个函数时,它就会给我抛出这个错误:
WindowsError: exception: access violation writing 0x00000000
我也不知道怎么获取我声明的自定义结构体,并把里面的每个元素转换成Python的浮点数。我查阅了这个PyDocs链接,但没有找到解决办法。
提前谢谢你。
编辑:
这是我使用的原始(根据建议修改过的)头文件("mydll.h"):
#ifndef MYDLL_H
#define MYDLL_H
extern "C" __declspec(dllexport)
#define EXPORT_DLL __declspec(dllexport)
EXPORT_DLL void ITERATE(struct res*, double z_r,double z_i,double c_r, double c_i, int iterations, double limit)
#endif
如果这个文件有问题的话,代码文件(非常短,只有一个函数):
#include <stdio.h>
#include <complex.h>
struct res {
double arr[3];
};
void __declspec(dllexport) ITERATE(struct res* result,double z_r,double z_i,double c_r, double c_i, int iterations, double limit)
{
/* The purpose of this function is, given two complex numbers,
an iteration number and a limit, apply a formula to these
two numbers for as many iterations as specified.
If at any iteration the result of the formula is bigger than
the limit, stop and return the number and the iteration it reached.
If after iterating they are still inside the limit, return the
number after all the iterations and the number of iterations
it has gone through.
Complex numbers are composed of a real part and an imaginary part,
and they must be returned separately.
*/
double complex z = z_r + z_i*I;
double complex c = c_r + c_i*I;
int actual_iter;
for (actual_iter = 1; actual_iter <= iterations; actual_iter++)
{
z = z*z + c;
if (cabs(z) > limit)
{
double value = actual_iter;
double z_real = creal(z);
double z_imag = cimag(z);
result.arr[0] = z_real;
result.arr[1] = z_imag;
result.arr[2] = value;
}
}
double value = iterations;
double z_real = creal(z);
double z_imag = cimag(z);
result.arr[0] = z_real;
result.arr[1] = z_imag;
result.arr[2] = value;
}
int main()
{
return 0;
}
1 个回答
2
这样返回结构体会有问题。因为不同的编译器处理结构体的方式不一样。我建议把函数的声明改成这样:
void __declspec(dllexport) ITERATE(struct res* result, double z_r,double z_i,
double c_r, double c_i, int iterations, double limit);
这样的话,结构体就会存放在用户的内存里,返回的时候就不会有任何不清楚的地方了。
当然,正如大卫所说,你可能需要使用不同的调用约定。