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

pdm*_*011 2 c# c++-cli stdout io-redirection

我有一个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<UnmanagedFP>(ip.ToPointer());

        //Call unmanaged DLL
        BusinessObject::DoStuff(cb);
        gch.Free();
        }

    private:
        String ^ m_progress;

    };
}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

Han*_*ant 7

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

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

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