A painless way to call a C # managed function (without return value) from unmanaged C ++?

I am tasked with supporting an outdated unmanaged C ++ system. I do not have access to the source of the entire system, but I have a source for several DLL extensions that, when included in the same directory as the main system, will load instead of the built-in default values.

I have used extensions in the past for small changes without problems. My problem now, however, is that they will ask me to reinstall one of the expansion libraries with a significant amount of additional functions. Creating this additional functionality in C # will be much faster (development time) and more maintainable (our team consists mainly of C # developers).

The dll extension has only two functions called by the base system. Two functions take values bool, int, uint, RECT, Point, CStringand return void. Some of the options they accept are const.

I really want to find a reliable way to associate these extension functions with C # (.NET 4). So far I have put a lot of effort into exploring COM-visible, Regasm, C ++ mixed modes and interaction libraries. I also lost a considerable amount of time proving conceptual designs during this study, and so far I have no working “bridge”.

What is the biggest method to run it and run it?


I am putting much more pressure on this project than usual - I literally start C # now and assume that I will somehow handle this.

.


.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
+3
3

: log4net Npgsql , with/clr.

, :

Visual Studio 2005 ManWrap, .NET Native ++ Code

, , log4net ( dll, /clr, /clr key code, 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_);
}

dll, DLL , - :

#pragma once

#pragma comment(lib, "Log4NetWrapper")

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

ReportDebugMessage .

+1

, , .

Extension Dll (unmanaged code) -> Managed C++ (wrapper) -> C# dll

:

http://www.codeproject.com/KB/mcpp/cpptomancpp.aspx

# ++

using namespace YourNameSpace; // the namespace of the c# routines

.

+1

Preet, Managed ++-, .

This article explains the whole process: http://www.codeproject.com/KB/mcpp/unmanaged_to_managed.aspx

I really did such things quite a few years ago, and all directions work very well - C # calling C ++ code, C ++ calling C # (through the Managed C ++ proxy) and passing the C # delegate to C ++ code, treating them as pointers to functions and calling them. I had examples of projects for this, I will try to find them.

+1
source

Source: https://habr.com/ru/post/1767646/


All Articles