Как передать указатели на DLL с помощью Win32: API? - PullRequest
2 голосов
/ 09 декабря 2008

Я пытаюсь передать 3 указателя на функцию DLL. У меня есть:

{

$code=1;
$len=100;
$str=" " x $len;

$function = new Win32::API(DLLNAME,'dllfunction','PPP','V');

$function->Call($code,$str,$len);

}

DLL определяется как void dllfunction(int* a, char* str, int* len); DLL изменяет все переменные, указанные тремя указателями.

Тем не менее, я запускаю segfaulting. В документации для Win32 :: API указано, что я должен использовать реальное имя переменной вместо ссылок на переменные Perl. Может кто-нибудь сказать мне, что мне не хватает? Спасибо.

* больше информации:

Я добавил printf() в DLL, чтобы распечатать адрес трех указателей, и printf в Perl, чтобы распечатать ссылку на три переменные. И я получаю следующее

DLL: код = 0x10107458 Ошибка = 0x10046b50 str = 0x10107460

Perl: код = 0x101311b8 Ошибка = 0x101312a8 str = 0x10131230

Есть идеи, почему DLL получает неправильные адреса?

**** Дополнительная информация

После большой отладки я обнаружил, что это происходит при возврате из функции DLL. Я добавил printf ("done \ n"); в качестве самой последней строки этой функции DLL, и это действительно выводит, то программа segfaults. Я предполагаю, что это происходит в Win32 :: API? Кто-нибудь испытывал это?

Кроме того, я могу получить доступ к начальным переменным всех трех переменных из DLL. Таким образом, указатель передается правильно, но по какой-то причине он вызывает ошибку при возврате из DLL. Может быть, это ошибка при попытке скопировать новые данные в переменную Perl?

Ответы [ 4 ]

3 голосов
/ 10 декабря 2008

AH !! Я понял это.

Проблема была в этом

  1. И, при желании, вы можете указать соглашение о вызовах, по умолчанию это __stdcall, или вы можете указать _cdecl.

Функция dll была экспортирована с extern "C" __declspec (dllexport), поэтому я решил, что мне следует использовать флаг _cdecl.

Win32 :: API ( 'DLL', 'dllfunction', 'РРР', 'V', '_ Cdecl');

работает!

спасибо всем.

0 голосов
/ 10 декабря 2008

ОК, я перешел по ссылке Адама на эту страницу . В соответствии с этим, звонок должен быть:

$function->Call(code, $str, len)

В примере кода используется функция с параметром LPSTR (по существу, char *), и она использует переменную, как и следовало ожидать, но этот бит здесь:

для указателей вы должны использовать имя переменной (без ссылок на Perl, просто имя переменной).

указывает на то, что код, указанный в этом посте , должен работать.

0 голосов
/ 10 декабря 2008

Я не программист Windows, но вижу:

для указателей вы должны использовать имя переменной

для меня означает имена переменных, а не сами переменные. Это работает?

$function->Call('code', 'str', 'len');

или, может быть

$function->Call('$code', '$str', '$len');

Кстати, я бы не ожидал, что адреса памяти будут одинаковыми. Win32::API потребуется преобразовать элементы данных Perl в нечто, понятное для Windows, и я серьезно сомневаюсь, что они будут занимать то же пространство физической памяти.

0 голосов
/ 09 декабря 2008

IANAPH, но я думаю, вам нужно использовать ссылку , например, так:

$function->Call(\$code, \$str, \$len)

Я менее всего уверен в том, что $ str - ему может не нужна ссылка. Segfault почти наверняка исходит от DLL, пытающейся записать в адрес памяти 1 (или 100, в зависимости от того, что он пытается записать первым).

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