How to disable void * when calling the platform

I need to call a function from C api contained in a dll. The prototype of the function is as follows.

int func( char* name, void* value ); 

where the contents of a pointer value can refer to any type depending on the name passed. I am not sure how to configure inport dll to properly sort this void *. I experimented with IntPtr, which seems to work, and the value is int, but I cannot get the values ​​for float properly, etc.

I am trying to import a function like this ...

 [DllImport("dllname.dll", CharSet = CharSet.Ansi)] public static extern int func( string name, ref IntPtr value ); 

Note that the value is the result. A pointer to a value of any type, that is, an address in the global memory region of a value of a known type (known to the caller). In c prog, the caller would have to cast that void * to the desired type and dereference to get the actual value stored there. The answers given so far seem to be based on the assumption that the function will write the result to the location of the pointer passed. My mistake, as I was not too specific. I'm sorry. C # is not my bag, and I don’t even know if IntPtr has a way here ...

+7
c #
source share
4 answers

The best way to handle this is to overload the function so that everything is creaky on the C # side. Like this:

 [DllImport("dllname.dll", CharSet = CharSet.Ansi)] public static extern int func(string name, out int value); [DllImport("dllname.dll", CharSet = CharSet.Ansi)] public static extern int func(string name, out float value); // etc, one each for each type 
+10
source share

You don't need a ref - IntPtr way to pass void* to your own code.

 [DllImport("dllname.dll", CharSet = CharSet.Ansi)] public static extern int func( string name, IntPtr value ); 

EDIT: C code can use the input to write to the required memory. The problem you are facing is that the managed code knows how much memory is allocated for each possible type of return value. Then a block of the appropriate size can be allocated using Marshal.AllocHGlobal or Marshal.AllocCoTaskMem , freed (according to which distribution method you use), use FreeHGlobal or FreeCoTaskMem as soon as the managed code is executed with the output value.

See the answer from @Alex Farber for an example.

+2
source share
 [DllImport ("dllname.dll", CharSet = CharSet.Ansi)] 
 public static extern int func (string name, IntPtr value); 

 ...

 // n - number of bytes which is enough to keep any type used by function
 IntPtr ptr = Marshal.AllocHGlobal (n);
 func (name, ptr);

 // Use Marshal.ReadByte, Marshal.ReadInt32 ... or Marshal.Copy
 // to copy from ptr filled by func to managed variable.  For example:
 byte b = Marshal.ReadByte (ptr);

 Marshal.FreeHGlobal (IntPtr);
+2
source share

Sometimes it may be easier to use this approach.

Declaration:

 [DllImport("dllname.dll", CharSet = CharSet.Ansi)] public static extern int func([MarshalAs(UnmanagedType.LPTStr)] string name, [MarshalAs(UnmanagedType.AsAny)] object value); 

Usage example for passing a value:

 func("some string", (int)12); func("some string", (double)12); 

Usage example for passing a string:

 func("some string", "test"); 

Usage example for passing a variable:

 int value = 12; func("some string", value); 
0
source share

All Articles