Calling C ++ dll functions returning char * from C #. Can't use DllImport ()
I have a C ++ dll with 2 functions
const char* getVersionText1(void);
void getVersionText2(const char** res);
Both functions return a string describing the product version. The first function returns it as a const char * (which means it allocates and handles localizes it internally), and the second gets a pointer to char * and just sets a pointer to a char * describing the version for it.
I want to call these functions from C # and display text. I cannot use the [dllimport ...] style as the order of the function calls is important. I call the constructor first than getVersion and finally the destructor. Therefore, the dll must first be loaded into memory.
Can you please post a few lines of code that print text for both functions. I am new to C # so sorry if you find my code is problematic I tried
static class NativeMethods{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
class Program{
// Define function pointers to entires in DLL
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr getVersionText1();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void getVersionText2(IntPtr );
static void Main(string[] args){
// Pointers to functions of DLL.
getVersionText1 f1;
getVersionText2 f2;
IntPtr pDll = NativeMethods.LoadLibrary("p:\\my.dll");
IntPtr pAddressOfFunctionToCall;
pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "getVersionText1 ");
f1 = (getVersionText1)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(getVersionText1));
pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "getVersionText2 ");
f2 = (getVersionText2)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(getVersionText2));
// Here I don't know what to do. It doesn't work ????
IntPtr verText = f1();
String s = Marshal.PtrToStringAuto(verText);
Console.WriteLine(s); // Doesnt work
// And how to use the second function. How do I sent a pointer to char* ???
}
}
source to share
You can make your calls here. There may be shorter alternatives that do utf8 / string conversions automatically.
[DllImport("mydll.dll")]
public static extern IntPtr getVersionText1(void);
public string getVersionTextConst()
{
IntPtr ptr = getVersionText1();
// assume returned string is utf-8 encoded
return PtrToStringUtf8(ptr);
}
[DllImport("mydll.dll")]
public static extern void getVersionText2(out IntPtr res);
public string getVersionTextConst()
{
IntPtr ptr;
getVersionText2(ptr);
// assume returned string is utf-8 encoded
String str = PtrToStringUtf8(ptr);
// call native DLL function to free ptr
// if no function exists, pinvoke C runtime free()
return str;
}
private static string PtrToStringUtf8(IntPtr ptr) // aPtr is nul-terminated
{
if (ptr == IntPtr.Zero)
return "";
int len = 0;
while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0)
len++;
if (len == 0)
return "";
byte[] array = new byte[len];
System.Runtime.InteropServices.Marshal.Copy(ptr, array, 0, len);
return System.Text.Encoding.UTF8.GetString(array);
}
source to share
If you need more speed, you can also do an unsafe read :
unsafe string GetString(IntPtr ptr) => new string((char*)ptr); // local function
IntPtr charPtr = f1();
var s = GetString(charPtr);
When you add the unsafe
method, VS will ask you if you want to allow unsafe code in the project: answer yes. Or manually "project properties / build / resolve unsafe code".
source to share