c# - 从非托管 C++ 调用托管 C# 函数(没有返回值)的无痛方式?

标签 c# c++

我的任务是维护遗留的非托管 C++ 系统。我无权访问整个系统的源代码,但我确实有一些扩展 dll 的源代码,当它们包含在与核心系统相同的目录中时,将加载它们而不是内置的默认值。

我过去曾使用这些扩展进行小的更改,没有出现问题。然而,我现在的问题是我被要求彻底检查一个具有大量额外功能的扩展 dll。在 C# 中创建这个额外的功能将明显更快(开发时间)并且更易于维护(我们的团队主要由 C# 开发人员组成)。

扩展dll 只有两个被核心系统调用的函数。这两个函数采用boolintuintRECTPointCString返回空值。它们接受的一些参数是 const

我真的很想找到一种可靠的方法将这些扩展函数桥接到 C# (.NET 4)。到目前为止,我已经投入大量精力研究 COM Visible、Regasm、c++ 混合模式和互操作包装库。在这项研究中,我还在概念验证项目上浪费了大量时间,到目前为止,我还没有一个有效的“桥梁”。

启动和运行它最轻松的方法是什么?


我在这个项目上承受的压力比平时大得多 - 我现在真的开始使用 C#,并假设我会以某种方式让它工作。

非常感谢帮助和反馈。


这是 .h 和 .def 文件:

modeldll.h

    #ifndef INC_MODELDLL_H
    #define INC_MODELDLL_H

    #ifdef MODELDLL_EXPORTS
    #define MODELDLL_API __declspec(dllexport)
    #else
    #define MODELDLL_API __declspec(dllimport)
    #endif

    typedef int (*model_updatemodel_t)(const bool update_model, const HWND hwnd, const RECT rect, const POINT next_point, const CString title);
    MODELDLL_API int UpdateModel(const bool update_model, const HWND hwnd, const RECT rect, const POINT next_point, const CString title);

    typedef int (*model_updatemodelpoint_t)(const bool update_model, const HWND hwnd, const RECT rect, UINT update, const POINT next_point);
    MODELDLL_API int UpdateModelPoint(const bool update_model, const HWND hwnd, const RECT rect, UINT update, const POINT next_point);

    typedef void (*model_process_message_t)(const char *message, const void *param);
    MODELDLL_API void ProcessMessage(const char *message, const void *param);

    #endif // INC_MODELDLL_H

modeldll.def:

    LIBRARY model.dll
    EXPORTS
    ProcessMessage    @1
    UpdateModel       @2
    UpdateModelPoint  @3

最佳答案

几年前我研究过这个主题:我想使用本地代码中的 log4net 和 Npgsql 库,即使使用我们的/clr 键也能编译。

Paul DiLascia 在他的两篇精彩文章中描述了这项技术背后的主要思想:

Managed Code in Visual Studio 2005 Use Our ManWrap Library to Get the Best of .NET in Native C++ Code

例如,这里有一些使用 native 代码中的 log4net 库的代码片段(此代码驻留在简单的非托管 dll 中,但您应该使用/clr 编译它,但使用/clr 关键代码编译并不是必需的从 native 代码使用此 dll):

// Log4NetWrapper.h

#pragma once

using namespace System;
//facade for log4net library (you may create something like this too)
ref class Log4NetWrapper
{
public:
    //I intentionally remove additional methods, because
    //I'm trying to show the main principle
    static void ReportDebugMessage(char* msg);
private:
    static property log4net::ILog^ Logger
    {
        log4net::ILog^ get();
    }
    static Object^ syncObject_ = gcnew Object();
    static String^ loggerName_ = "";
};

//C-interface that could be accessed from native code
extern "C" 
{
    _declspec(dllexport) void ReportDebugMessage(char* msg) 
    {
        Log4NetWrapper::ReportDebugMessage(msg);
    }

}

// This is the main DLL file.

#include "stdafx.h"

#include "Log4NetWrapper.h"

void Log4NetWrapper::ReportDebugMessage(char* msg) 
{
    String^ data = gcnew String(msg);
    Logger->Debug(data);
}
log4net::ILog^ Log4NetWrapper::Logger::get()
{
    if ( loggerName_ == nullptr )
        return log4net::LogManager::GetLogger("");
    return log4net::LogManager::GetLogger(loggerName_);
}

将此代码编译为 native dll,然后将此 dll 添加到您的 native 项目,向该项目添加如下内容:

#pragma once

#pragma comment(lib, "Log4NetWrapper")

extern "C"
{
    _declspec(dllimport) void ReportDebugMessage(char* msg); 
}

并使用 ReportDebugMessage 从 native 代码访问托管代码。

关于c# - 从非托管 C++ 调用托管 C# 函数(没有返回值)的无痛方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3845022/

相关文章:

c# - 一个 super 简单的 MVVM-Light WP7 示例?

c# - WMI Code Creator for Bitlocker Status - 我哪里出错了?

c++ - 使用 substr 时出错

c++ - 从属名称的模板消歧器

c++ - 用getline()填充结构字段

c# - 从字节数组读取 C# 中的 C/C++ 数据结构

javascript - 文化敏感的字符串排序

c# - mysql语法错误

c++ - make_shared() 的可调试替代品

c++ - QChartView、RubberBand 和鼠标右键行为