Array of strings as return value from C to C#? [closed]

Array of strings as return value from C to C#? [closed]



How does one return an array of strings (char**) from a native C function into a managed string type in C#?


char**


string



This works:


C:
char* get_text()
size_t length = ...;
char *text = (char *)CoTaskMemAlloc((length + 1) * sizeof(char));
// populate text...
return text;


C#:
[DllImport(LibName, EntryPoint = "get_text", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string GetText();



This, however, I cannot get to work:


C:
char** get_texts()
size_t count = ...;
char **texts = (char **)CoTaskMemAloc(count * sizeof(char*));
for (size_t i = 0; i < count; ++i)
size_t length = ...;
texts[i] = (char *)CoTaskMemAlloc((length + 1) * sizeof(char));
// populate texts[i]

return texts;


C#:
[DllImport(LibName, EntryPoint = "get_texts", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(???)]
private static extern string GetTexts();



I've tried setting the return type to marshal as LPArray and SafeArray with SafeArraySubType = VarEnum.VT_LPSTR, but I can't get it to work. Using LPArray seems to suggest I should pass in parameters for the size of the array (along with the subtype, which is LPStr), but I don't know the size at the time of the call.


LPArray


SafeArray


SafeArraySubType = VarEnum.VT_LPSTR


LPArray


LPStr



How can this be achieved?



This question appears to be off-topic. The users who voted to close gave this specific reason:





char ** is a pointer to pointer of char, not an array of strings, not an array of pointers. Oh, and don't cast the result of malloc or void * in general.
– too honest for this site
Sep 3 at 15:00



char **


malloc


void *





Arrays are too clunky in C and C++ to allow this to work. The pinvoke marshaller cannot know how many elements are present in the array. You don't know either. Yes, SafeArray is a workaround, of BSTR. Post your code.
– Hans Passant
Sep 3 at 15:26





It c language a string is an array of bytes with each string terminated with ''. C# uses two byte objects for each character while c uses only one and that is why you use bytes. The last string array will terminate with two '';
– jdweng
Sep 3 at 15:44





@jdweng No, there are no double null terminated arrays here
– David Heffernan
Sep 3 at 16:20




1 Answer
1



Try following :


[DllImport("LibName", EntryPoint = "get_texts", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetTexts();

static void Main(string args)

List<string> results = new List<string>();

IntPtr data = GetTexts();

IntPtr tmpPtr = IntPtr.Zero;
while(data != null)

string str = Marshal.PtrToStringAnsi(data);
results.Add(str);
data += 1;




The code assumes the array of strings are stored as an array of points. Sometime in c this is not the case and then the code below may work


[DllImport("LibName", EntryPoint = "get_texts", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetTexts();

static void Main(string args)

List<string> results = new List<string>();

IntPtr data = GetTexts();

IntPtr tmpPtr = IntPtr.Zero;
Boolean first = true;
string str = "";
do

if (first)

str = Marshal.PtrToStringAnsi(data);
first = false;

results.Add(str);
data += str.Length + 1;
str = Marshal.PtrToStringAnsi(data);

while (str.Length > 0);





The first block is a promising start but fails in a number of ways. It fails to deallocate any of the memory. Perhaps more seriously, the pointer arithmetic is wrong. You are incrementing by a single byte, but need to increment by the size of a pointer. Finally, you are missing one level of indirection. That is data is char** but your code implies it is char*. This approach indicated by this first block of code could be made to work, but all of these defects would need to be fixed. The second block of code is totally bogus though.
– David Heffernan
Sep 3 at 16:20



data


char**


char*





He we go again with are usual arguments. You do not post your own answer, just give negative remarks. The OP asks " How does one return an array of strings". We can only tell from the posting that the memory is continuous but cannot tell how the array is organized. It can only be organized two possible ways so I gave two solutions. One should work.
– jdweng
Sep 3 at 23:21





Nope. The memory is not continuous. There are N + 1 distinct allocations. N individual strings and an array of length N containing those pointers. You can certainly tell how the array is organised because the C code is clear. Neither of the approaches work. The first block is heading in the right direction. Did you compile and run the code yet? Then you'd know that your answer was wrong.
– David Heffernan
Sep 4 at 5:53


Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

How do I collapse sections of code in Visual Studio Code for Windows?

ャフサォクコ ケウ,コ,ワ メ,ロスョノ゙,クネ,フムカヤヲニ,エコ゚ツ ウイオン゙ケワサネォキモュキォウイノンコチ゚メヌナイゥフュ,カヒウネェ ネ,ホノケ,ムュキ ッボーミュハ,チ ツス ィ メウイマヤ,゙ウチ ヅ ロ,ォジヌェ ャヌット ェ,マャ,チナエヒネソキツテ トホヲヲミーァ