使用ctypes模块来访问C中写入的DLL时出错 [英] Error when using ctypes module to acess a DLL written in C
问题描述
我有一个单一的功能的DLL它获得五个双重和一个int:
__ declspec(dllexport)struct res ITERATE (double z_r,double z_i,double c_r,double c_i,int iterations,double limit)
一个由三双数组组成的自定义结构体系结构:
struct res {
double arr [3] ;
};
要返回我这样做的值:
struct res result; / *前面的代码* /
result.arr [0] = z_real; / *只有三个随机双打* /
result.arr [1] = z_imag;
result.arr [2] = value;
返回结果;
我已经用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将结果分配给任何东西。
但是,每当我尝试使用这些值调用该函数,它会把它抛给我: p>
WindowsError:异常:访问冲突写入0x00000000
我也不知道如何捕获我声明的自定义结构,并将其每个元素转换为Python浮点数。我已经调查了这个PyDocs链接,但没有效果。
提前谢谢。
编辑:
这是原始的(根据建议修改)标题(mydll.h):
#ifndef MYDLL_H
/ pre>
#define MYDLL_H
externC__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)
{
/ *这个函数的目的是给出两个复数,
一个迭代次数和一个限制,对这些
两个数字应用一个公式,用于指定的迭代次数。
如果在任何迭代中,公式的结果大于
的限制,停止并返回数字及其到达的迭代。
如果经过迭代,它们仍然处于限制之内,则在所有迭代之后返回
数字,并返回
的次数。
复数由实部和虚部组成,
,它们必须单独返回。
* /
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;
}
解决方案返回有问题这样的结构。并不是所有的编译器都以相同的方式返回这样的结构。我宁愿将函数声明更改为:
void __declspec(dllexport)ITERATE(struct res * result,double z_r, double z_i,
double c_r,double c_i,int iterations,double limit);
这样结构在用户的内存中,结构体将如何
当然,正如David所说,您可能需要使用不同的调用约定。
I have a DLL with one single function That gets five doubles and one int:
__declspec(dllexport) struct res ITERATE(double z_r,double z_i,double c_r, double c_i, int iterations, double limit)
It retuns a custom struct caled res which consists of a three-double array:
struct res { double arr[3]; };
To return the values I do this:
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;
I've compiled it with MinGW and I'm trying to use it in python to do something like this:
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.
But, whenever I try call the function with those values, it wil throw this to me:
WindowsError: exception: access violation writing 0x00000000
I also don't know how to catch the custom structure I declared and convert each of it's elements into Python floating points. I've looked into this PyDocs link but to no avail.
Thank you in advance.
EDIT:
This is the original (modified according to suggestions) header used ("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
And, in case something might be wrong with it, the code file (it's very short, just one function):
#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; }
解决方案There is a problem with returning structs like that. Not all compilers return such structures the same way. I'd rather change the function declaration to this:
void __declspec(dllexport) ITERATE(struct res* result, double z_r,double z_i, double c_r, double c_i, int iterations, double limit);
That way the struct is in the user's memory, and there is no ambiguity on how the struct will be returned.
Of course, as David said, you may have to use a different calling convention.
这篇关于使用ctypes模块来访问C中写入的DLL时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!