【发布时间】:2019-06-03 20:03:01
【问题描述】:
我目前正在学习 C++(最终为 Hooks 创建 DLL)。我在 C# 方面有优势,想通过 pInvoke/DllImports 访问 DLL。
我正在使用 VS 2019(和 .NET Framework 4.7.2)。作为用于学习目的的示例,我复制了 DLL 以及 C++(控制台应用程序),如下所述:https://docs.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=vs-2019。这工作得很好(正如预期的那样)。
现在,当我开始尝试将 DLL 导入 C# 项目时,我遇到了问题(我认为这与 DllImport 相关)
在示例 (c++) 控制台应用程序(正在运行)中:
int main()
{
// Initialize a Fibonacci relation sequence.
fibonacci_init(1, 1);
// Write out the sequence values until overflow.
do {
std::cout << fibonacci_index() << ": " << fibonacci_current() << std::endl;
} while (fibonacci_next());
// Report count of values written before overflow.
std::cout << fibonacci_index() + 1 << " Fibonacci sequence values fit in an " << "unsigned 64-bit integer." << std::endl;
}
在 C# 测试控制台应用程序中(无法正常工作):
class Program
{
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void fibonacci_init(ulong a, ulong b);
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl))]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool fibonacci_next();
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern ulong fibonacci_current();
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern uint fibonacci_index();
static void Main(string[] args)
{
// Initialize a Fibonacci relation sequence.
fibonacci_init(1, 1);
// Write out the sequence values until overflow.
do {
Console.WriteLine($"{fibonacci_index()}: {fibonacci_current()}");
} while (fibonacci_next());
// Report count of values written before overflow.
Console.WriteLine($"{fibonacci_index() + 1} Fibonacci sequence values fit in an unsigned 64-bit integer.");
}
}
在工作 (C++) 应用程序中,循环达到 92 并打印
92: 12200160415121876738 然后退出循环并打印93 Fibonacci sequence values fit in an unsigned 64-bit integer.
但是,在失败的 (C#) 应用程序中,它一直工作到 92: 12200160415121876738,但 fabonacci_next() 并没有退出循环,而是继续返回 true 并继续循环 92: 12200160415121876738 行(不再递增,并且永不退出)。
对于 C# 中的 DllImport,我都尝试过:
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl))]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool fibonacci_next();
和:
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl))]
public static extern bool fibonacci_next();
无论哪种方式,结果都相同。如果有人可以向我解释我在使用 DllImport 时做错了什么(导致它永远不会返回 true,当同一个 DLL 在链接到 C++ 控制台应用程序时正常工作时)。
--- 更新 ---
因此,上述示例的解决方案将[return: MarshalAs(UnmanagedType.Bool)] 更改为[return: MarshalAs(UnmanagedType.I1)] 确实有效(在下面的cmets 中GSerg 提供的链接中提供了更多重要的相关信息)。
--- 更新 2 ---
(@David)我故意(并且错误地)省略了导出,因为它们位于我提供给原始 DLL“演练”的链接中(我很抱歉)。为了问题的完整性,出口是:
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
extern "C" MATHLIBRARY_API void fibonacci_init(unsigned long long a, unsigned long long b);
extern "C" MATHLIBRARY_API bool fibonacci_next();
extern "C" MATHLIBRARY_API unsigned long long fibonacci_current();
extern "C" MATHLIBRARY_API unsigned fibonacci_index();
【问题讨论】:
-
请解释一下投反对票,也许我可以改写一下?
-
C++ 的
bool不是 C# 的bool。UnmanagedType.Bool是 C++ 的BOOL,而不是bool。见stackoverflow.com/q/32110152/11683。 -
没有这也是一个问题(参见stackoverflow.com/q/53898839/11683)。
-
@SimonMourier 他们改变了事情,我想我必须等待 24 小时才能回答我自己的问题。 (另外我希望其他具有更好“术语”技能的人会首先回答:)
-
@DavidHeffernan 同意,我理解,因此我的更新和道歉指出我在您之前的评论之后错误地排除了它。