如何在C#中使用C++ DLL导出的接口指针

2024-01-04

我有一个用 C++ 编写的 DLL,它导出一个函数 CreateRisk。该函数返回一个接口指针,如下:

extern "C"
{
    __declspec(dllexport) IRisk* __stdcall CreateRisk()
    {
        return new  Risk();


    }
}

IRisk 派生自 IUnknown,并具有自定义方法Calculate:

class IRisk: public IUnknown                               
{
public:
    virtual int __stdcall Calculate(int i,double s) = 0;  
};

Risk 类实现了 IRisk 接口(这里省略了实现)。

我想要的是调用c#中的函数CreateRisk并获取对IRisk的引用。

我在c#中定义了一个包装接口

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]        
    public interface IRisk
    {
        [PreserveSig]                                            
        int Calculate(int i,double s);
    }

我在 C# 中添加了一个 dll 条目

    [DllImport("Risk.dll")]
    extern static IntPtr CreateRisk();

我可以在 C# 中调用 CreateRisk 并获取 IntPtr 的值类型。有没有办法将 IntPtr 编组到 C# IRisk 接口,以便我可以调用 C# 中的Calculate 方法?

我尝试过 Marshal.GetIUnknownForObjectInContext、Marshal.GetObjectForIUnknown,但无济于事。

我知道创建一个 COM 组件可以做到这一点。然而,COM组件需要向系统注册。我想避免这些麻烦,让C#直接使用C++ dll导出的接口。

PS:

以下是我的风险类实现:

class IRisk : public IUnknown                               
{
public:
    virtual int __stdcall Calculate(int i,double y ) = 0;  
};

class Risk:public IRisk
{
    int count;
public:
    Risk();
    virtual int __stdcall Calculate( int i ,double y);
    virtual ULONG __stdcall AddRef();
    ULONG __stdcall Release();
    HRESULT __stdcall QueryInterface(const IID& riid,void **ppvObject);
};

Risk::Risk(){
    count=0;
}

ULONG __stdcall Risk::AddRef()
{
    return ++count;
}
ULONG __stdcall Risk::Release()
{
    return --count;
}
HRESULT __stdcall Risk::QueryInterface(const IID& riid,void **ppvObject) {
    *ppvObject=this;
    AddRef();
    return S_OK;
}
int __stdcall Risk::Calculate(int i ,double y) {
    return (int)(i+y);
}

以下将起作用:

[DllImport("Risk.dll")]
extern static IRiskAssessment CreateRisk();

您需要将 GUID 添加到界面:

[Guid("your GUID goes here")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]        
public interface IRiskAssessment
{
    [PreserveSig]                                            
    int Calculate(int i,double s);
}

显然,您需要在 C# 代码中使用与 C++ 代码中使用的相同的 GUID!

Update

查看您的 C++ COM 对象实现,明显的错误在于QueryInterface。你不得返回S_OK对于所有 GUID。只返回S_OK对于您实现的接口。返回E_NOINTERFACE对于其他人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在C#中使用C++ DLL导出的接口指针 的相关文章

  • 使用链表进行堆排序

    我想知道是否有人曾经使用链表进行堆排序 如果他们可以提供代码 我已经能够使用数组进行堆排序 但尝试在链表中进行排序似乎不切实际 而且在你知道的地方很痛苦 我必须为我正在做的项目实现链接列表 任何帮助将不胜感激 我也用C 答案是 你不想在链表
  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include
  • 在 Mono 中反序列化 JSON 数据

    使用 Monodroid 时 是否有一种简单的方法可以将简单的 JSON 字符串反序列化为 NET 对象 System Json 只提供序列化 不提供反序列化 我尝试过的各种第三方库都会导致 Mono Monodroid 出现问题 谢谢 f
  • C# 中一次性对象克隆会导致内存泄漏吗?

    检查这个代码 class someclass IDisposable private Bitmap imageObject public void ImageCrop int X int Y int W int H imageObject
  • MVC 5 中具有 ASP.NET Identity 的 Autofac 不会验证 OWIN 管道中的安全标记

    我在 MVC 5 中设置了 AutoFac 来与 ASP NET Identity 一起使用 表面上一切似乎都工作正常 即用户可以创建帐户并登录 但后来我发现 当安全标记更改时 用户不会注销 通过在 AspNetUsers 表中进行暴力破解
  • JavaScript 错误:MVC2 视图中的条件编译已关闭

    我试图在 MVC2 视图页面中单击时调用 JavaScript 函数 a href Select a JavaScript 函数 function SelectBenefit id code alert id alert code 这里 b
  • OpenGL:如何检查用户是否支持glGenBuffers()?

    我检查了文档 它说 OpenGL 版本必须至少为 1 5 才能制作glGenBuffers 工作 用户使用的是1 5版本但是函数调用会导致崩溃 这是文档中的错误 还是用户的驱动程序问题 我正在用这个glGenBuffers 对于VBO 我如
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • 如何在 Javascript 中连接 C# ActiveX 事件处理程序

    我尝试使用几个代码片段将 ActiveX 对象与 Javascript 事件处理程序挂钩 我无法确定为什么事件处理程序没有被调用 带有项目的 Github 存储库 https github com JesseKPhillips Csharp
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • C++ 指针引用混淆

    struct leaf int data leaf l leaf r struct leaf p void tree findparent int n int found leaf parent 这是 BST 的一段代码 我想问一下 为什么
  • 构建 C# MVC 5 站点时项目之间的处理器架构不匹配

    我收到的错误如下 2017 年 4 月 20 日构建 13 23 38 C Windows Microsoft NET Framework v4 0 30319 Microsoft Common targets 1605 5 警告 MSB3
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 在 C# 的 WebAPI 中的 ApiController 上使用“传输编码:分块”提供数据

    我需要服务分块传输使用编码数据API控制器 因为我无权访问HttpContext or the Http请求 我有点不知道在哪里写入响应以及在哪里刷新它 设置如下 public class MyController ApiControlle
  • 如果将变量设置为等于新对象,旧对象会发生什么?

    假设我们有一个 X 类not有一个超载的operator 功能 class X int n X n 0 X int n n n int main X a 1 an object gets constructed here more code
  • ContentDialog Windows 10 Mobile XAML - 全屏 - 填充

    我在项目中放置了一个 ContentDialog 用于 Windows 10 上的登录弹出窗口 当我在移动设备上运行此项目时 ContentDialog 未全屏显示 并且该元素周围有最小的填充 在键盘上可见 例如在焦点元素文本框上 键盘和内
  • 如何为有时异步的操作创建和实现接口

    假设我有数百个类 它们使用 计算 方法实现公共接口 一些类将执行异步 例如读取文件 而实现相同接口的其他类将执行同步代码 例如将两个数字相加 为了维护和性能 对此进行编码的好方法是什么 到目前为止我读到的帖子总是建议将异步 等待方法冒泡给调
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有

随机推荐