Я новичок в C ++ / CLI, но кодирую управляемый код много лет ... очевидно, слишком много лет. :)
Попытка написать оболочку для неуправляемого класса, предоставленного третьей стороной, и я вижу некоторые странные вещи. Я надеюсь, что вы все можете помочь мне избавиться от того, в чем заключается моя глупость и что на самом деле странно.
CLI Wrapper:
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)
Вот неуправляемый.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^
, или если это даже требуется. Если это так, то некоторая помощь с явным синтаксисом будет принята с благодарностью.
Я также сузил вызов, который выдает ошибочные утверждения, до //1
, возвращая return ""; //3
. Эти утверждения указывают на попытку изменить / удалить память, которой не существует в куче, к которой имеет доступ текущая среда выполнения. Связано ли это с необходимостью маршалирования возвращаемого значения UnmangedClass::getSomeString()
?
Надеюсь, я просто упускаю здесь простую концепцию, и нет проблем со сторонним кодом. Пожалуйста, дайте мне знать, если я могу предоставить более подробную информацию и извинения за почти полное незнание дедушки всех языков.
Заранее спасибо за любую информацию или "указатели";
EDIT: добавление 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();
}
РЕДАКТИРОВАТЬ: Добавление подписи Dumpbin.exe Unmanged.dll! UnmangedClass :: getSomeString ()
(public: class std::basic_string<code><char,struct std::char_traits<char>,class std::allocator<char> >
__thiscall Codegen :: getSomeString (void))