我正在运行一个简短的实验,以查看从本机C ++(MFC)应用程序显示一些WPF窗口会有多困难。在看到this和后来的this之后,我决定在.NET类库.DLL周围使用C ++ / CLI包装DLL。
[native C++ .exe] -> [C++/CLI wrapper .lib] -> [C# Class Library .dll]
可以认为,这将使我的本机C ++应用程序保持不受管理,并且不需要使用/ clr编译选项。
在跳过显示窗口并启动调度程序所需的一些障碍之后,我随后使沙盒代码正常工作。一个本机控制台应用程序启动,显示一个WPF窗口,允许用户输入数字,并在关闭窗口时返回该数字并将其写入控制台输出。
现在,我过去使用CLI进行反向操作(从托管调用非托管代码),但是朝这个方向前进让我有些困惑。
在阅读了有关如何为.NET可执行文件初始化CLR的一些资料之后,例如在this SO answer's comments中讨论了CLR“进程”以及如何将Execution Engine引导启动的讨论,我想知道在不对主要可执行文件进行管理或与.NET相关联的情况下,何时以及如何发生所有这些事情?另外,CLR组件的“生命周期”是什么-如果我进行单个方法调用,垃圾收集器和JIT编译器是否会初始化和销毁?他们是否接受我的流程直到退出?这会以任何方式影响我的本机应用程序吗?
我的测试项目的代码如下所示,并且据我所知可以正常工作。
将CLIWrapper.lib添加到“ AdditionalDependencies”中
#include "CLIInterface.h"
int main()
{
APIWrapper wrapper;
int rint = wrapper.GetAnInteger();
char buffer[100];
snprintf(buffer, sizeof(buffer), "Value: %d\n", rint);
std::cout << buffer;
}
class APIWrapperPrivate;
class APIWrapper
{
private:
APIWrapperPrivate* _private;
public:
APIWrapper();
~APIWrapper();
int GetAnInteger();
};
#include <msclr\auto_gcroot.h>
#using "..\CSharpLibrary\bin\Debug\CSharpLibrary.dll"
using namespace System;
using namespace System::Runtime::InteropServices;
class APIWrapperPrivate
{
public:
msclr::auto_gcroot<CSharpLibrary::TheCSharpInterface^> theCSharpInterface;
};
class __declspec(dllexport) APIWrapper
{
private:
APIWrapperPrivate* _private;
public:
APIWrapper()
{
_private = new APIWrapperPrivate();
_private->theCSharpInterface = gcnew CSharpLibrary ::TheCSharpInterface();
}
~APIWrapper()
{
delete _private;
}
int GetAnInteger()
{
return _private->theCSharpInterface->GetAnItegerValue();
}
};
public class TheCSharpInterface
{
public int GetAnItegerValue()
{
int anIntegerValue;
ThreadStart ThreadProc = new ThreadStart(() =>
{
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
SomeWindow window = new SomeWindow();
window.Closed += (sender, e) =>
{
anIntegerValue = window.Power;
Dispatcher.CurrentDispatcher.InvokeShutdown();
};
window.Show();
Dispatcher.Run();
});
Thread t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
t.Join();
return this.anIntegerValue;
}
}
带有整数滑块控件的wpf窗口