I look forward to hearing from you.
Write a function that returns a string (mixed alphanumeric) with char in C++ and
I'm thinking of using that function from C# to receive a string.
I looked it up and found that there were steps like passing a string from C#, but
I'm at a loss because I can't find a way to return it from C++.
If anyone knows, could you please let me know?
In C/C++, the "function returns a string" action has two patterns:
1. A called function dynamically takes memory with malloc()
and stores a string there (strdup
)
).
2. The calling function takes a fixed-length buffer, and the called function stores a string there (snprintf
)
Which one is this case?
You can use StringBuilder
for the latter.This eliminates the need for unsafe and automatically encodes.
C++ side
extern "C"_declspec(dllexport)bool_stdcallGetText(char*buf,size_tbufsize){
if(bufsize<4)return false
buf[0] = 'a';
buf[1] = '\x82'; // 82a0 = CP932 'Ah'
buf[2] = '\xa0';
buf[3] = '\0';
return true;
}
C# side
[DllImport("example.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi)]
static external Boolean GetText (StringBuilder's, Int32bufsize);
// CharSet.Ansi specifies that OS standard local specific encoding should be automatically converted to UTF-16
// CP932 → UTF-16 for Japanese OS
System.Text.StringBuilder sb=new System.Text.StringBuilder(256);
GetText(sb, sb.Capacity);
Console.WriteLine(sb.ToString()); //a
In the former case malloc()
series results are different depending on when and how free()
is performed.
You have to look at the C/C++ specifications or implementations to get answers.
:: If you use the memory saved by CoTaskMemAlloc, you can target GC on the .Net side, so
C++ to C# string passing is easier on the C# side by implementing the following link:
https://limbioliong.wordpress.com/2011/06/16/returning-strings-from-a-c-api/
C/C++
extern "C"_declspec(dllexport) char *__stdcall StringReturnAPI01()
{
charszSampleString[] = "Hello World";
ULONGulSize=strlen(szSampleString)+sizeof(char);
char*pszReturn=NULL;
pszReturn=(char*)::CoTaskMemAlloc(ulSize);
// Copy the contents of szSampleString
// to the memory pointed to by pszReturn.
strcpy(pszReturn, szSampleString);
// Return pszReturn.
return pszReturn;
}
C#
[DllImport("<path to DLL>", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
return: MarshallAs (UnmanagedType.LPStr)
public static external string StringReturnAPI01();
static void CallUsingStringAsReturnValue()
{
string strReturn01 = StringReturnAPI01();
Console.WriteLine("Returned string:"+strReturn01);
}
Compile /unsafe with C# and use byte* (pointer) or
Instead of using /unsafe, you can pinned the area and pass the address.
https://stackoverflow.com/questions/1579446/how-can-i-pass-a-pointer-to-an-integer-in-c-sharp
To quote with a little improvement,
【Unsafe usage pattern <
unsafe static void TestMethod()
{
fixed (byte*buffer=new byte [4096])
{
int maxSize = buffer.Length;
GetBuffer(buffer, ref maxSize);
}
}
【Unsafe not used pattern >
byte[] buf = new byte [kBufSize];
GCHANDLE HANDLE = GCHANDLE.Alloc (buf, GCHANDLEType.Pined);
// An address is fixed by securing an area and pinning it.
IntPtrp=handle.AddrOfPinnatedObject();
int size = buf.Length;
intret=GetBuffer(p,ref size); // DLLImported C++ function
handle.Free();
You can convert the byte array you receive into characters to match the encoding of the string.
© 2024 OneMinuteCode. All rights reserved.