Ошибка при использовании модуля ctypes для доступа к DLL, написанной на C - PullRequest
1 голос
/ 17 июля 2011

У меня есть DLL с одной функцией, которая получает пять двойных и одно целое:

__declspec(dllexport)  struct res ITERATE(double z_r,double z_i,double c_r, double c_i, int iterations, double limit)

Возвращает пользовательскую структуру caled 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 , но безрезультатно.

Заранее спасибо.

EDIT:

Это оригинальный (измененный в соответствии с предложениями) заголовок ("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 голосов
/ 18 июля 2011

Существует проблема с возвратом таких структур.Не все компиляторы возвращают такие структуры одинаково.Я бы лучше изменил объявление функции на это:

void __declspec(dllexport) ITERATE(struct res* result, double z_r,double z_i, 
    double c_r, double c_i, int iterations, double limit);

Таким образом, структура находится в памяти пользователя, и нет никакой двусмысленности относительно того, как структура будет возвращена.

OfКонечно, как сказал Дэвид, вам, возможно, придется использовать другое соглашение о вызовах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...