gpt4 book ai didi

c# - 通过托管 C++ 包装器从非托管 C++ dll 运行 C# 函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:50:50 27 4
gpt4 key购买 nike

我正在开发一个 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 个项目,我无法让它们工作)。我试过使用委托(delegate),但程序崩溃了。

或者也许有更简单的方法来做到这一点。

谢谢!

代码如下,非常简单:

首先,我有非托管 dll:C++项目,Win32 Console Application,编译成dll

定义.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 类项目

包装器.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
}
}
}

最佳答案

太多代码无法真正理解,但我对类似问题的解决方案涉及一个看起来像这样的委托(delegate)。

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void UserFunctionCallback(IntPtr context, int nvalues,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]IntPtr[] values);

如果有帮助,我可以添加更多代码。

关于c# - 通过托管 C++ 包装器从非托管 C++ dll 运行 C# 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29240617/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com