【问题标题】:How do I pass pointers to a DLL using Win32:API?如何使用 Win32:API 将指针传递给 DLL?
【发布时间】:2008-12-09 20:06:45
【问题描述】:

我正在尝试将 3 个指针传递给 DLL 函数。我有:

{ $代码=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会修改三个指针指向的所有变量。

但是,当我运行它时,我出现了段错误。 Win32::API 的文档指定我应该使用实际变量名而不是 Perl 变量引用。谁能告诉我我错过了什么?谢谢。

*更多信息:

我在DLL中添加printf()打印出三个指针的地址,在Perl中添加printf打印出三个变量的引用。我得到以下内容

DLL:代码 = 0x10107458 错误 = 0x10046b50 str = 0x10107460

Perl:代码 = 0x101311b8 错误 = 0x101312a8 str = 0x10131230

知道为什么 DLL 得到错误的地址吗?

****更多信息

经过多次调试,我发现这是从DLL函数返回时发生的。我添加了 printf("done\n");作为这个 DLL 函数的最后一行,它确实输出,然后程序段错误。我猜它发生在 Win32::API 中?有人经历过吗?

另外,我可以从 DLL 访问所有三个变量的初始变量。所以指针是正确传递的,但由于某种原因,它在从 DLL 返回时会导致段错误。尝试将新数据复制到 Perl 变量时可能出现段错误?

【问题讨论】:

  • 您可能希望更改其中一个标签以反映这也是一个与 Perl 相关的问题。

标签: perl winapi dll pointers


【解决方案1】:

啊!!我想通了。

问题是这样的

  1. 您还可以选择指定调用约定,默认为“__stdcall”,或者您可以指定“_cdecl”。

dll 函数是使用 extern "C" __declspec(dllexport) 导出的,所以我想也许我应该使用 '_cdecl' 标志。

Win32::API('dll','dllfunction','PPP','V','_cdecl');

有效!

谢谢大家。

【讨论】:

  • 好发现 - 我什至没有考虑调用约定(但我应该有,因为大多数 Win32 API 使用 __stdcall 而不是 _cdecl)。
【解决方案2】:

IANAPH,但我认为您需要使用 reference,如下所示:

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

我最不确定的是 $str - 它可能不需要参考。段错误几乎肯定来自 DLL 试图写入内存地址 1(或 100,取决于它首先尝试写入的地址)。

【讨论】:

  • IANAPH 也可以,但根据search.cpan.org/~acalpini/Win32-API-0.41/…,您不应该使用 $str 参数的引用;我不确定其他两个参数。
  • 我也试过了,发送所有三个引用,发送 2 个 int 引用和 1 个 str 变量。但是,它仍然存在段错误。我同意你的观点,当 dll 试图访问错误的内存地址时,肯定会发生段错误,但我不能放弃找出导致它的原因:
【解决方案3】:

好的,我点击了亚当的链接到this page。据此,调用应该是:

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

示例代码使用了一个带有 LPSTR(本质上是一个 char*)参数的函数,并且它使用了你所期望的变量,但是这里有点:

对于指针,您必须使用变量名(没有 Perl 引用,只是一个普通的变量名)。

似乎表明我在这篇文章中列出的代码应该工作。

【讨论】:

  • 我也试过了,但我仍然遇到段错误。我把 > 作为指针,你必须使用一个变量名(没有 Perl 引用,只是一个普通的变量名)。至于做 $function->Call($code, $str, $len) 而不是 $functino->Call(\$code,\$str,\$len);
【解决方案4】:

我不是 Windows 程序员,但看到了:

对于指针,您必须使用变量名

对我来说意味着变量名,而不是变量本身。这行得通吗?

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

或许

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

顺便说一句,我不希望内存地址相同。 Win32::API 需要将 Perl 数据元素转换成 Windows 可以理解的东西,我严重怀疑它们会占用相同的物理内存空间。

【讨论】:

  • 在稍微考虑了指针之后,我想了很多。但我能够从 DLL 中读取每个变量的初始值。所以它正确地通过了点,但是从 DLL 返回时会出现段错误。
猜你喜欢
  • 2011-08-17
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 2018-09-03
  • 2011-05-11
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多