通过托管C++包装程序从非托管C++dll运行C#函数
Run a C# function from an unmanaged C++ dll through a managed C++ Wrapper
我正在处理一个C#项目,该项目使用一些封装在dll中的非托管C++代码。我必须将该dll加载为引用(而不是DllImport),所以我正在编写一个托管C++包装器,作为C#和dll之间的桥梁。
我可以很容易地从C#调用dll函数,只需从C#调用包装器中的等效函数,然后从包装器调用dll函数。然而,dll中有一些回调函数应该调用C#函数,而这一部分不起作用。我已经学习了一些关于这种互操作的教程(stackoverflow,microsoft,codeproject),但它们都很旧,我无法使它们工作。
这个想法是dll正在处理实时数据,每次dll生成一些结果时,它都应该调用Program.cs中的一个函数,该函数使用这些结果。
我正在处理的代码非常庞大,所以我制作了一个非常简单的场景,其中包括所有不起作用的内容。
在Program.cs中,我试图告诉dll:"进行此函数测试,并在完成后调用它"。然后,为了测试它,我强制它运行回调函数。但我发现了几个错误。
虽然wrapper编译并生成wrapper.dll,但当我在C#项目中加载它时,函数M_setCallback不存在?。
我想知道是否有人能帮我一把,或者给我看一个教程,解释如何做到这一点(我发现的教程没有我必须使用的3个项目,我无法让它们发挥作用)。我尝试过使用委托,但程序崩溃了。
或者也许有一种更简单的方法可以做到这一点。
谢谢!
这是代码,非常简单:
首先,我有非托管dll:C++项目,Win32控制台应用程序,编译成dll
defs.h
namespace JJLibrary
{
typedef void (__stdcall *MYCALLBACK) (bool mybool, int myint);
}
unmanaged_dll.h
#ifndef JJAPI_H
#define JJAPI_H
#ifdef UNMANAGED_EXPORTS
#define JJ_API __declspec(dllexport)
#else
#define JJ_API __declspec(dllimport)
#endif
#include "defs.h"
namespace JJLibrary
{
JJ_API void U_helloWorld();
JJ_API void U_setCallback( MYCALLBACK theCallback );
JJ_API void U_runCallback();
}
#endif //JJAPI_H
unmanaged_dll.cpp
#include "unmanaged_dll.h"
#include <iostream>
using namespace std;
namespace JJLibrary
{
MYCALLBACK m_callback = 0;
JJ_API void U_helloWorld()
{
cout << "Unmanaged: Hello world" << endl;
}
JJ_API void U_setCallback( MYCALLBACK theCallback )
{
cout << "Unmanaged: Setting callback" << endl;
m_callback = theCallback;
}
JJ_API void U_runCallback()
{
bool b = true;
int i = 25;
cout << "Unmanaged: Running callback: " << b << " " << i << endl;
if (m_callback)
m_callback(b, i);
// In the final application b and i are generated here after processing data, I give them values for testing
// When they are generated, call the function in C#
}
}
包装器:C++CLR类项目
wrapper.h
#include "defs.h"
#include <iostream>
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace JJLibrary;
using namespace std;
namespace wrapper {
public ref class Wrapper
{
public:
void M_helloWorld();
void M_setCallback( MYCALLBACK theCallback );
void M_runCallback( bool mybool, int myint );
};
}
包装纸.cpp
#include "stdafx.h"
#include "wrapper.h"
#include "defs.h"
#include <iostream>
using namespace wrapper;
using namespace JJLibrary;
using namespace std;
void Wrapper::M_helloWorld()
{
cout << "Managed: Hello World" << endl;
U_helloWorld();
}
void Wrapper::M_setCallback( MYCALLBACK theCallback )
{
cout << "Managed: Setting callback" << endl;
U_setCallback( theCallback);
}
void Wrapper::M_runCallback(bool mybool, int myint)
{
cout << "Managed: Running callback" << endl;
U_runCallback(mybool, myint);
}
最后,Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using wrapper;
namespace CS
{
class Program
{
void Test(bool mybool, int myint)
{
Console.WriteLine(!mybool);
Console.WriteLine(2*myint);
}
static void Main(string[] args)
{
Wrapper myWrapper = new Wrapper();
myWrapper.M_helloWorld();
myWrapper.M_setCallback(Test);
myWrapper.M_runCallback(true, 25); // --> false 50
string s = Console.ReadLine(); // Pause
}
}
}
太多的代码无法真正理解,但我对类似问题的解决方案涉及一个看起来像这样的委托。
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void UserFunctionCallback(IntPtr context, int nvalues,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]IntPtr[] values);
如果这有帮助,我可以添加更多的代码。
- 可视化C++:发布模式的运行时库作为'Multi-threaded Debug DLL'
- 如何使特定程序仅从安装的路径运行以避免DLL劫持
- c++ 注入器运行,但不注入 DLL
- 在运行时加载C++ DLL
- 尝试运行 gmp 时未找到 MPIR.dll
- C++ DLL 运行时错误"abc.dll is not a valid WIN32 application" 。请帮助解决这个问题
- 如何将我的程序转换为.dll文件并使用rundll32.exe在cmd中运行它?
- 是否有可能让 c++ dll 在后台运行 python 程序并让它填充向量图?如果是这样,如何?
- 使用 C++ dll 运行 c# 应用程序会生成无法加载异常
- C\C++构建的dll在LabView中实时运行
- 如何在运行时从 c++ 中的 DLL 文件创建对象?
- 在注入的 Dll 的 DllMain 中运行代码导致注入超时
- CLR dll 无法运行托管 DLL,除非它位于 exe 目录(或其子目录)内
- MSVCP140.dll尽管设置了 /MT 运行时库
- 通过托管C++包装程序从非托管C++dll运行C#函数
- 使用 libstdc++6.dll 运行代码时出错
- 使用 DLL 运行时,按钮上不显示位图
- 无法对libhydro.dll运行java本机访问
- 当从DLL运行时,c++ cdialgex丢失ParentWnd
- MSVCR100D.dll运行时错误