Любопытная проблема DllImport при передаче LONG-параметра повреждения памяти - PullRequest
0 голосов
/ 24 октября 2011

Я создал функцию DLL для использования внутри C # с использованием DLLImport, но у меня возникают проблемы при вызове метода, поскольку у меня возникают проблемы с повреждением памяти;

[DllImport("mydll.dll", EntryPoint = "callinmydll")]
public static extern int testdllcall(double *firstinput, long firstcount, double *secondoutput, long secondcount);

Вот часть заголовка библиотеки C ++;

extern "C" {              

mydll_API int callinmydll(double *in, long firstcount, double *out, long secondcount);

}

Реализация.

mydll_API int callinmydll(double *in, long firstcount, double *out, long secondcount)
{
    for( int i =0 ; i < 10 ; i++ ) 
    {
        *(out + i) = (*(in + i) + 10 );
    }

    return 0;
}

Теперь, когда моя функция DLLImport вызывает функцию callinmydll и передает ей действительные данные, это то, где вещи становятся интересными.Указатель in содержит данные, как и firstcount.Хотя все, что находится за пределами этой точки, искажено.Зачем?Любопытно, что я переставил свою функцию так: double , double *, long, long, теперь повреждение происходит после третьего параметра.Мне интересно, что происходит, так как я передаю действительные данные;два действительных указателя и int приводятся к int64.

Help!

1 Ответ

4 голосов
/ 24 октября 2011

В Win32 C long по-прежнему 32-битный. Ваша подпись C # использует long, который является 64-битным. Ваш второй и четвертый параметры должны быть int в сигнатуре C #.

См. таблицу для получения дополнительной информации.

Итак, ваша подпись выглядит так:

[DllImport("mydll.dll", EntryPoint = "callinmydll")]
public static extern int testdllcall(double *firstinput, int firstcount, double *secondoutput, int secondcount);

Кроме того, убедитесь, что ваше соглашение о вызовах правильное, как указывал Ramhound в комментариях. Ваша функция C выглядит так, как будто она использует соглашение CDecl, а в .NET по умолчанию используется StdCall. Вы можете установить соглашение о вызовах в атрибуте:

[DllImport("mydll.dll", EntryPoint = "callinmydll", CallingConvention = CallingConvention.Cdecl)]
...