【发布时间】:2011-04-11 11:05:03
【问题描述】:
我是 C++/CLI 的新手,但多年来一直在编写托管代码......显然太多年了。 :)
尝试为第 3 方提供的非托管类编写包装器,但我看到了一些奇怪的东西。我希望你们都可以帮助我清除我的笨拙和真正奇怪的地方。
CLI 包装器:
public ref class Wrapper
{
public:
Wrapper(const float* flts, unsigned int fltlen, int offset)
{
_unmanagedClass = new UnmanagedClass(flts, fltlen, offset);
}
~Wrapper()
{
delete _unmanagedClass;
}
String^ getSomeString()
{
string x = _unmanagedClass->getSomeString(); //1
String^ ret = gcnew String(x.c_str()); //2
return ret; //3
}
private:
UnmanagedClass* _unmanagedClass;
};
我还应该注意,我在标题中有这些指令;
#pragma managed(push, off)
#include "Unmanaged.h"
#pragma comment(lib, "lib\\Unmanaged_dll.lib")
#pragma managed(pop)
这里是 Unmanaged.h;
class UNMANGED_API UnmanagedClass
{
public:
UnmanagedClass(const float* flts, uint fltlen, int offset);
string getSomeString() { return _someString; }
private:
string _someString;
};
这一切都会编译。然后就会出现陌生感/缺乏经验。
在 DEBUG 配置中对此进行调试时,UnmanagedClass::getSomeString() 似乎返回了一个合理/预期的字符串值。我可以通过在//2 上设置断点并查看x 的值来看到这一点。如果我步进到//3,我可以看到ret 的值是x。但是,如果我尝试跳出/越过 //3,我会收到一些失败的断言(BLOCK_TYPE_IS_VALID 和 _CrtIsValidHeapPointer),并且调试器会停止,永远不会返回到托管实现。
在 RELEASE 配置中调试它时,我没有得到失败的断言并返回到我的托管实现,但 getSomeString() 返回的字符串值在我偷看的地方都是垃圾; //2、//3 以及托管实现中。
我已经用几种不同的方式修改了代码,但都无济于事。
我认为需要围绕 //2 进行一些编组,但我还没有找到任何真正重要的事情,比如如何将 basic_string 编组为 System::String^,或者如果它甚至是必需的。如果是这样,那么我们将非常感谢您对显式语法的帮助。
我还通过返回return ""; //3 将产生失败断言的调用范围缩小到//1。这些断言指向尝试修改/删除当前运行时有权访问的堆上不存在的内存。这是否与需要编组 UnmangedClass::getSomeString() 的返回值有关?
希望我只是在这里遗漏了一些简单的概念,并且第 3 方代码没有问题。如果我能提供更多细节,请告诉我,并为我几乎完全不了解所有语言的祖父而道歉。
提前感谢您提供任何信息或“指针”;
编辑:添加 C# 托管客户端实现;
public unsafe string GetString(List<float> flts )
{
float[] fltArr = flts.ToArray();
Wrapper wrap;
fixed (float* ptrFlts = fltArr)
{
wrap = new Wrapper(ptrFlts , fltArr.Length, 0);
}
var x = wrap.getSomeString();
return x.ToString();
}
编辑:添加 Unmanged.dll!UnmangedClass::getSomeString() 的 Dumpbin.exe 签名
(public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Codegen::getSomeString(void))
【问题讨论】:
标签: c++-cli marshalling unmanaged wrapper managed