使用ctypes模块来访问C中写入的DLL时出错 [英] Error when using ctypes module to acess a DLL written in C

查看:210
本文介绍了使用ctypes模块来访问C中写入的DLL时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个单一的功能的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 
#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
/ pre>

如果有什么可能是错误的,代码文件(很简单,只是一个功能):

  #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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆