c++ - powershell调用具有结构类型参数的c ++ dll的导出函数
问题描述
struct foostruct
{
int B;
int A;
int D;
};
int foofunc(foostruct foo)
{
return foo.A;
}
我已经导出FooFunc
了test.dll
现在我正在尝试从 powershell 调用它
$source = @"
public struct foostruct {
public int B;
public int A;
public int D;
}
"@
Add-Type -TypeDefinition $Source -IgnoreWarnings
$bar = New-Object foostruct
$bar.B = 1;
$bar.A = 2;
$bar.D = 3;
$MethodDefinition = @'
[DllImport("test.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int foofunc(foostruct foo);
'@
$dll = Add-Type -MemberDefinition $MethodDefinition -Name 'dll' -PassThru -IgnoreWarnings
这会引发错误
The type or namespace name 'foostruct' could not be found (are you missing a using directive or an assembly reference?)
我尝试按照这里提到的移动fostruct
内部的定义,但是当我使用下面的方法调用它时,我得到了错误。$MethodDefinition
Unable to cast object of type 'System.Object[,]' to type 'System.Object[]'
$Result = $dll::foofunc($bar)
解决方案
The type or namespace name 'foostruct' could not be found (are you missing a using directive or an assembly reference?)
使用两个单独的 s的原因Add-Type
是它们在幕后创建了单独的程序集,而“MemberDefinition”程序集不知道“TypeDefinition”程序集,因此无法将foostruct
类型解析为实现。
尝试 1 - 失败
Add-Type
因此,让我们根据您链接到的答案将这两个声明移到一个“MemberDefinition”中:
$source = @"
public struct foostruct
{
public int B;
public int A;
public int D;
}
[DllImport("test\\test\\x64\\Debug\\test.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int foofunc(foostruct foo);
"@
Add-Type -MemberDefinition $Source -Name "dll";
$bar = New-Object foostruct
$bar.B = 1;
$bar.A = 2;
$bar.D = 3;
$dll::foofunc($bar);
运行这个对 来说很好Add-Type
,但是尝试使用foostruct
会给出这个错误:
New-Object : Cannot find type [foostruct]: verify that the assembly containing this type is loaded.
At C:\src\so\pinvoke\test.ps1:25 char:8
+ $bar = New-Object foostruct
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
该foostruct
类型对 PowerShell 可见DllImport
,但对 PowerShell 不可见 :-(
尝试 2 - 失败
好的,让我们尝试将其作为“TypeDefinition”Add-Type
来代替:
$source = @"
public struct foostruct
{
public int B;
public int A;
public int D;
}
[DllImport("test\\test\\x64\\Debug\\test.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int foofunc(foostruct foo);
"@
Add-Type -TypeDefinition $Source;
$bar = New-Object foostruct
$bar.B = 1;
$bar.A = 2;
$bar.D = 3;
由于编译器期望包装在类Add-Type
中的“浮动” ,这会产生编译错误:[DllImport]
Add-Type : c:\Users\Mike\AppData\Local\Temp\cchnscq4\cchnscq4.0.cs(14) : Expected class, delegate, enum, interface, or
struct
c:\Users\Mike\AppData\Local\Temp\cchnscq4\cchnscq4.0.cs(13) : [DllImport("test\\test\\x64\\Debug\\test.dll",
CharSet=CharSet.Unicode, SetLastError=true)]
c:\Users\Mike\AppData\Local\Temp\cchnscq4\cchnscq4.0.cs(14) : >>> public static extern int foofunc(foostruct foo);
c:\Users\Mike\AppData\Local\Temp\cchnscq4\cchnscq4.0.cs(15) :
At C:\src\so\pinvoke\test.ps1:22 char:1
+ Add-Type -TypeDefinition $Source;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Except
ion
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand
尝试 3 - 成功
我们可以在上面$Source
的“TypeDefinition”Add-Type
版本中调整字符串以使编译器满意:
$source = @"
using System.Runtime.InteropServices;
public struct foostruct
{
public int B;
public int A;
public int D;
}
public static class NativeMethods
{
[DllImport("test\\test\\x64\\Debug\\test.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int foofunc(foostruct foo);
}
"@
Add-Type -TypeDefinition $Source;
$bar = New-Object foostruct
$bar.B = 1;
$bar.A = 2;
$bar.D = 3;
[NativeMethods]::foofunc($bar);
请注意,foofunc
它现在是该类的静态成员[NativeMethods]
。
此版本的输出如下:
2
这基本上是$bar.A
C++ 函数返回的值,所以一切似乎都按要求工作。
笔记
我无法重现您的Unable to cast object of type 'System.Object[,]' to type 'System.Object[]'
错误,所以我无法真正解释这一点,但希望上面的答案可以帮助您解决问题......
推荐阅读
- excel - 链接更新时暂停 VBA 脚本
- c++ - (反)序列化枚举类
- amazon-web-services - 尽管 CloudWatch 代理正在运行,但缺少 CloudWatch 日志组
- database - MongoDB 如何从 $lookup 远程集合中 $project(限制字段)?
- javascript - ConstantSourceNode 设置的振荡器频率错误
- jquery - 如何在列表框中选择一个值并将其与其 optgroup 标签克隆到另一个列表框
- python - 如何使小部件随 PyQt5 中的窗口缩放?
- clojure - 在 Clojure 中使用 Java 哈希图
- machine-learning - Keras 中两次损失的总和(感知和 MSE)
- android - 访问 zzbgl 并覆盖已弃用的 API 时出错