I am new to C ++ / CLI, but have been coding managed code for many years ... apparently too many years. :)
An attempt to write a wrapper for an unmanaged class provided by a third party, and I see some strange things. I hope you all can help me pick weeds, what is my noobility and what is really strange.
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();
I should also note that I have these directives in the header;
#pragma managed(push, off) #include "Unmanaged.h" #pragma comment(lib, "lib\\Unmanaged_dll.lib") #pragma managed(pop)
Here is Unmanaged.h;
class UNMANGED_API UnmanagedClass { public: UnmanagedClass(const float* flts, uint fltlen, int offset); string getSomeString() { return _someString; } private: string _someString; };
It all compiles. Then comes the oddity / lack of experience.
When debugging in the DEBUG configuration, UnmanagedClass::getSomeString() seems to return the value of the resonant / expected string value. I see this by setting a breakpoint at //2 and looking at the value of x . If I go to //3 , I see that ret has the value x . However, if I try to exit / above //3 , I get a couple of unsuccessful statements ( BLOCK_TYPE_IS_VALID and _CrtIsValidHeapPointer ) and _CrtIsValidHeapPointer , never returning to a managed implementation.
When debugging this in the RELEASE configuration, I do not get unsuccessful statements, and I return to my managed implementation, but the string value returned by getSomeString() is garbage wherever I look in it; //2 , //3 , as well as in a managed implementation.
I massaged the code in several ways, but to no avail.
I think there is something like Mashalling that needs to be done around //2 , but I could not find anything that really gets home, as far as this can be done, to basic_string in System::String^ or even if it is required. If so, then some help with explicit syntax would be greatly appreciated.
I also narrowed down the call, which causes unsuccessful statements to //1 , returning return ""; //3 return ""; //3 . These statements indicate an attempt to modify / delete memory that does not exist on the heap that the current runtime has access to. Is this due to the need to UnmangedClass::getSomeString() return value of UnmangedClass::getSomeString() ?
Hopefully I just skipped a simple concept here and there is no problem with third-party code. Please let me know if I can provide more detailed information and apologize for the almost complete ignorance of the great pope of all languages.
Thanks in advance for any information or "pointers";
EDIT: adding a managed C # client implementation;
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(); }
EDIT: Adding Dumpbin.exe Signature to Unmanged.dll! UnmangedClass :: getSomeString ()
(public: class std::basic_string <char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Codegen:: getSomeString (void))