gpt4 book ai didi

C# 调用 C++ 第 3 方 DLL(无源代码)引发异常 - 不兼容 PInvoke

转载 作者:行者123 更新时间:2023-11-28 05:37:36 25 4
gpt4 key购买 nike

我将 VS 2015 Community 与 ASP.NET MVC Web 应用程序一起使用,该应用程序使用第 3 方 C++ DLL 我没有源代码。文档非常稀少,与第 3 方 DLL 作者的任何有用的交流也是如此。

我问过一个相关的SO Question并从@Steven 那里得到了很好的回答。我已经根据他的回答修改了我的代码,并试图成功调用第 3 方 C++ DLL。代码:

//调用动态链接库

MyDLLInput _DLLInput = new MyDLLInput();
{
SomeList = new int[288],
...
SomeInt = 22,
SomeDbl = 1.45,
...
PathtoData = "C:\\Some\\Path\\To\\Data"
};

var ids = new int[] { 0, 12, 33, 67, 93 };
Array.Copy(ids, _DLLInput.SomeList, ids.Length);

// Call DLL Entry Point
MyDLLOutput _DLLOutput = MyDLL.Unit(_DLLInput);

引发异常:

Method's type signature is not PInvoke compatible.

//C# 输入结构

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyDLLInput
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 288)]
public int[] SomeList;
...
public int SomeInt;
public double SomeDbl;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string PathtoData;
};

//C# 输出结构

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyDLLOutput
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 288)]
public int[] SomeList;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 288)]
public double[] SomeDblArray;
...
public int SomeInt; // Same as input
public double SomeDbl; // Same as input
}

//C# DLLImport

public class MyDLL
{
[DllImport("My_DLL.dll",
EntryPoint = "?Unit@@YA?AUDLLOutput@@UDLLInput@@@Z",
CallingConvention = CallingConvention.Cdecl)]
public static extern MyDLLOutput Unit(MyDLLInput UnitInput);
}

//C++ My_DLL.h

#define  EPS_API __declspec(dllexport) 

struct DLLInput
{
int SomeList[288];

int SomeInt;
double SomeDbl;

char PathtoData[256];
};

struct DLLOutput
{
int SomeList[288];
double SomeDblArray[288];
...
int SomeInt;
double SomeDbl;
};

EPS_API DLLOutput Unit(DLLInput UnitInput);

我想我一定很接近,但还没有找到任何有帮助的 SO 或 Google 结果。有人看到我做错了什么吗?

最佳答案

扩展本所说的内容。

您需要将常量定义移除到可互操作结构之外。通过将结构的布局声明为顺序的,编译器期望成员数量完全相同,以完全相同的顺序声明,声明的每种类型,两侧的大小完全相同(即在 C++ 和 C# 中)。这些 const 声明添加到内存布局中,因此签名不兼容。

char 在 C# 和 C++ 中的大小不同,byte 是(尽管它们可以根据平台而改变,但两种类型都保证至少 8 位)。您可以编码一个 byte 数组而不是 string,但两者都可以。

创建与 C++ char 数组(相同大小)兼容的 byte 数组。

UTF8Encoding utf8 = new UTF8Encoding();
public byte[] PathToData = new byte[256];
PathToData = utf8.GetBytes(pathToDataString);

但另一方面,如果文档稀缺且作者没有帮助,我个人会三思而后行使用这个第 3 方。调用它是一回事,调试它是另一回事。

关于C# 调用 C++ 第 3 方 DLL(无源代码)引发异常 - 不兼容 PInvoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37902919/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com