我有一个C#应用程序调用经由一些C++/CLI编组码的本地C++ DLL:从非托管的DLL的stdout捕捉在C#呼叫者
C# - > C++/CLI - > C++(无CLR)
我想让DLL在运行时将字符串更新发回给调用应用程序。目前,非托管DLL将输出写入标准输出。基本上我需要在UI中捕获这个输出。
在我脱壳非托管EXE这可以通过简单地从被呼叫者重定向标准输出到在结合到文本面板UI数据的字符串缓冲区来实现其它情况。
我没有使用P /调用或脱壳它作为一个exe,由于互操作层执行非原始类型的基本编组调用DLL的选项。非托管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;
};
}
预先感谢。
该设置将用于C++/CLI应用程序,不是吗?问题说应用程序(它调用C++/CLI DLL)是用C#编写的。或者即使您将其设置在C++/CLI DLL项目中,它也可以工作吗? – svick
确实,更正了。谢谢! –
感谢您的回复。有没有一种方法可以将stdout从控制台重定向回主应用程序,只要使用上述架构,即不使用.Net ShelledProcess类或类似的东西?理想情况下,我希望能够在UI中显示之前对stdout进行后处理,以删除不必要的文本并添加各种标记和其他格式。 – pdm2011