从C#调用者中的非托管DLL捕获stdout

我有一个C#应用程序通过一些C ++ / CLI编组代码调用本机C ++ DLL:

C# – > C ++ / CLI – > C ++(无CLR)

我希望DLL在运行时将字符串更新发回给调用应用程序。 目前,非托管DLL将输出写入stdout。 基本上我需要在UI中捕获此输出。

在我正在炮轰非托管exe的其他情况下,这可以通过简单地将stdout从被调用者重定向到绑定到文本面板的UI数据中的字符串缓冲区来实现。

我没有选择使用P / Invoke调用DLL或将其作为exe来shell,因为互操作层执行非基本类型的基本编组。 非托管DLL没有CLR支持,必须保持这种方式。

我使用代表( http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.100).aspx )取得了有限的成功,因为似乎总是存在托管和非托管世界发生冲突的地方。 以链接中的示例为例,将来自C ++ / CLI伪装的托管委托作为本机函数指针传递给DLL,但回调是在C ++ / CLI类的范围之外定义的,因此无法访问从中传入的托管委托。调用层(C#)。

理想情况下,我想定义一个接受非托管字符串的类,并可以将这些字符串转换为托管并回调到UI层,但如果此类具有托管字符串的必要支持,则无法将其传递给非托管代码。

我可能错过了一个简单的重定向技巧,它允许捕获stdout而不在层之间传递字符串(例如,从通过委托接收的C ++ / CLI重定向stdout)。 如果这是不可能的,任何人都可以提出替代技术吗?

托管C ++:

using namespace System::Runtime::InteropServices; using namespace System; namespace BusinessObjectInterop { typedef void (__stdcall *UnmanagedFP)(std::string); //Callback function public delegate void SetProgressDelegate(std::string); void SetProgress(std::string s) { Console::WriteLine(s); //set m_progress - could use managed delegate passed from UI and exposed in static method in CIntermediate? } public ref class CIntermediate { public: //Invoked by managed (C#) UI void ^ CallBusinessObject(Object ^ data, String ^ progress) { //Do some data marshalling... //... m_progress = progress; //Create wrapper for managed delegate SetProgressDelegate^ fp = gcnew SetProgressDelegate(SetProgress); GCHandle gch = GCHandle::Alloc(fp); IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp); UnmanagedFP cb = static_cast(ip.ToPointer()); //Call unmanaged DLL BusinessObject::DoStuff(cb); gch.Free(); } private: String ^ m_progress; }; } 

提前致谢。

对,这不起作用。 一个DLL没有stdout,一个进程就是这样。 并且您的流程不会创建一个,因为它是GUI应用程序,也不能重定向工作,因为这需要另一个流程。

解决方法很简单。 确保您已选择Debug配置。 右键单击您的项目,属性, 链接器,系统。 将SubSystem设置更改为“Console(/ SUBSYSTEM:CONSOLE)”应用程序选项卡。 将输出类型设置更改为“控制台应用程序”。

按F5。 Presto,现在你有一个控制台窗口,显示DLL的调试输出。 和你的常规GUI。