I have a c++ dll with 2 functions
const char* getVersionText1(void);
void getVersionText2(const char** res);
Both function return a string describing the version of the product. First function returns it as const char* (which means it allocates and deal locates it internally) and the second one gets a pointer to char* and just sets it to point to a char* describing the version.
I want to call those functions from C# and display the text. I cant use [dllimport ...] style since the order of the calling of functions is important. I first call constructor than getVersion and finally the destructor. So dll must be loaded to memory first.
Can you please post the few lines of codes that print the text for both functions. I am new to C#, so sorry if you find my code 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* ???
}
}
If the C++ library function returns char*
, C# code will treat it as IntPtr
and Marshal.PtrToStringAnsi()
will convert it into C# string
.
IntPtr verText = f1();
string s = Marshal.PtrToStringAnsi(verText);
Console.WriteLine(s);
Here's a way of making your calls. There may be shorter alternatives that perform the 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's 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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With