0

I have some of unmanaged C++ dynamic library and C# GUI application, using it. I need to pass a pointer to structure with embedded buffer and some integral meta data members. Structure allocated on C# side to C++ library. Then library populates it, returns to C# application and application uses it in some ways, releasing finally.

My first approach was using StringBuilder as embedded string buffer, but i receive an exception on runtime which says it is not allowed to use StringBuilder as structure member. Also I got advice to use string preinited with suitable buffer size. I've tryed this approach, but it seems bufefr passed via string cannot be modified on C++ part. Is it right?

// C++ typedef struct SomeStruct{ wchar_t* stringBuffer; // buffer uint64_t size; // some additional integral fields int64_t mTime; // some additional integral fields }; // Native library API method MYCDLL_API uint8_t __stdcall getSomeStructures(uint32_t index, SomeStruct* struct, uint64_t stringBufferSize); // C# part [DllImport(myLibraryname, CallingConvention = CallingConvention.StdCall)] static extern RetCode getSomeStructures(UInt32 index, ref SomeStruct someStruct, UInt64 stringBufferSize); 

How this task could be solved? As, I mentioned I need to pass a reference to structure with embedded modifyable character buffer from C# to C++.

2 Answers 2

1

I'd declare that field as IntPtr.

struct SomeStruct { IntPtr stringBuffer; ulong size; long mTime; } 

Declare the function like this:

[DllImport(myLibraryname)] static extern byte getSomeStructures( uint index, ref SomeStruct someStruct, ulong stringBufferSize ); 

Use Marshal.AllocHGlobal() and Marshal.FreeHGlobal() to allocate and free the buffer. Use Marshal.PtrToStringUni() to create a string from the pointer.

SomeStruct someStruct; someStruct.stringBuffer = Marshal.AllocHGlobal(1024); try { // initialize the rest of someStruct byte retval = getSomeStructures(index, ref someStruct, 1024); // check retval for errors string str = Marshal.PtrToStringUni(someStruct.stringBuffer); } finally { Marshal.FreeHGlobal(someStruct.stringBuffer); } 

I've assume that the parameter named size is a byte size. If it is actually a length, then you need to account for the characters being 16 bytes wide, and you should change the parameter name to length rather than size.

Sign up to request clarification or add additional context in comments.

Comments

0

Try to use following declaration of structure:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct SomeStruct { [MarshalAs(UnmanagedType.LPWStr)] public string stringBuffer; public UInt64 size; public Int64 mTime; }; [DllImport("Win32Project1.dll", EntryPoint = "GetSomeStructures")] static extern int GetSomeStructures( uint index, ref SomeStruct str, ulong stringBufferSize); static void Main(string[] args) { var a = new SomeStruct(){ stringBuffer = "asd", size=10, mTime = 20 }; Console.WriteLine(GetSomeStructures(1, ref a, 1)); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.