将 DLL 包装C++一秒钟以在 C# 中加载



我正在尝试公开来自DLL(我们称之为foo.dll)的函数以在C#中使用。但是,我无法访问源代码,所以我想我可能能够编写第二个DLL (bar.dll),其中包括第一个,通过从 foo.dll 返回结果来重新实现函数。我确实有 .lib 和 .h 文件,所以我希望我可以写一个小工具来浏览标头并生成我的"包装器"dll(这是正确的术语吗?

我为此设置了一个非常简单的测试,自己实现 foo.dll。我对C++很陌生,所以请温柔一点。

福.H

#pragma once
double Add(double a, double b);

傅.cpp

#include <stdio.h>
#include "foo.h"
double Add(double a, double b)
{
return a + b;
}

我构建了这个并将 .lib 引用到我的 bar 项目中,并在 foo.h 中复制。

酒吧.H

#pragma once
extern "C"
{
namespace foo {
#include "foo.h"
}
__declspec(dllexport) double Add(double a, double b);
}

酒吧.cpp

#include <stdio.h>
#include "bar.h"
__declspec(dllexport) double Add(double a, double b)
{
return foo::Add(a, b);
}

到目前为止如此简单。然后,我尝试使用 DllImport 将其引入 C# 中:

using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("bar.dll", CallingConvention = CallingConvention.StdCall)]
private static extern double Add(double a, double b);
static void Main(string[] args)
{
Console.WriteLine("PRE");
Console.WriteLine(Add(1.5, 8.5));
Console.WriteLine("POST");
Console.ReadKey();
}
}
}

但是,当我运行它时,我只会得到"PRE"输出,程序只是等待。到目前为止,我已经通过错误消息进行了故障排除,但我不确定如何弄清楚在这种情况下发生了什么。

如果我重新实现 bar.cpp 返回 a + b,C# 应用程序按预期运行,输出: 前 10.0 发布

我已经阅读了很多关于这个主题的文章,有些人建议在声明我的变量时在名称前添加__stdcall,但这给了我一个 StackOverflow 错误。

这是我的第一篇SO帖子(当然我已经潜伏了多年),所以如果我能做些什么来改进这个问题,请随时告诉我。

既然你正在创建bar.dll无论如何,使用 C++/CLI 来包装foo.dll; 如果你的 P/Invokes 变得不平凡(就像处理遗留C++代码一样),你会很高兴你朝着这个方向前进。

namespace BarAssembly
{
public ref struct Bar abstract sealed // "abstract sealed" == C#'s "static"
{
static double Add(double a, double b) {
return foo::Add(a, b);
}
}
}

您的 C# 代码现在很简单

static void Main(string[] args)
{
Console.WriteLine("PRE");
Console.WriteLine(BarAssembly.Bar.Add(1.5, 8.5));
Console.WriteLine("POST");
Console.ReadKey();
}

无需[DllImport],尽管您必须添加对bar.dll程序集的引用。

这可能是调用约定,但较新版本的 .NET 实际上非常适合为大多数 CC 违规引发异常。我建议在你的C++包装器中贴一些printf,看看你是否能弄清楚它挂在哪里。

选项 B - 实际上有一个名为 SWIG 的包装生成器,它完全可以执行您正在为数十种不同语言所做的工作。效果很好。

最新更新