PInvoke method contained in a native structure - c#

I am trying to re-create some C++ sample API usage code in C#.
It's looking like I might need to create a C++/CLI wrapper to make the API functions accessible to the managed world, but I'd like to avoid that if possible. The API library itself only has a single exported function: data_api_func_tab.
This is what the C++ API usage looks like:
//
// .h file
//
typedef struct _DATA_API_FUNC_TAB {
short (*api_init)();
// ... lots of other methods ...
} DATA_API_FUNC_TAB
extern "C" typedef short (* MAPIINIT)(short);
// ... lots of other methods ...
#undef EXTERN
#ifdef _MAIN
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN MAPIINIT ncm_api_init;
// ... lots of other methods ...
public:
UCHAR SomeVariable;
void SomeMethod( arguments );
//
// .cpp file
//
/// Constructor
CWidgetDataApi::CWidgetDataApi()
{
SomeVariable = 0;
m_hInstHdl = ::LoadLibrary(_T(".\\NATIVEAPI.dll"));
if( NULL != m_hInstHdl )
{
DATA_API_FUNC_TAB* p_data_api_func_tab =
(DATA_API_FUNC_TAB*) ::GetProcAddress(m_hInstHdl, "data_api_func_tab");
SomeVariable = 1;
if( p_data_api_func_tab == NULL )
{
::FreeLibrary(m_hInstHdl);
m_hInstHdl = NULL;
SomeVariable = 0;
}
else
{
api_init = (MAPINIT) p_data_api_func_tab->api_init;
// ... lots of other methods ...
short Ret = api_init(index);
}
}
}
/// Method
void CWidgetDataApi::SomeMethod( arguments )
{
// ... Makes use of the various other methods ...
}
//
// Usage in another class
//
DataAPI = new CWidgetDataApi;
if( DataAPI->SomeVariable == 1 )
{
DataAPI->SomeMethod( arguments );
...
}
Since I can't use reflection on the native library (not to mention it would be slow), PInvoke seems to be the only way in.
I have recreated the appropriate structures in C# and tried the following PInvoke signatures,
[DllImport("NATIVEAPI.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern struct data_api_func_tab { };
[DllImport("NATIVEAPI.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern short api_init([In, Out] ref _DATA_API_FUNC_TAB data_api_func_tab);
but they produce the exception
Unable to find an entry point named '... whatever I try...' in NATIVEAPI.dll
I've searched around for a way to do this but only seem to find unmanaged to C++/CLI solutions. Is what I am attempting to do even possible (given that the individual methods contained in the structure are not exported)?

This is a pretty far out API. Instead of exporting functions, the library exports the address of a struct containing function pointers. Notice how the C++ code call GetProcAddress and then interprets the result as a pointer to a struct and not as is more common, as a pointer to a function.
From the documentation of GetProcAddress, with my emphasis:
Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).
You cannot use DllImport to access this library's export because DllImport is for functions rather than variables.
Here's what you must do:
Use LoadLibrary to load the DLL and obtain a module handle as an IntPtr.
Call GetProcAddress to obtain the address of the struct.
Use Marshal.PtrToStructure to get a managed struct containing the function pointers.
Use Marshal.GetDelegateForFunctionPointer for each member of the struct to obtain a delegate which you can then call.
When you are done with the library unload it by calling FreeLibrary. You can omit this step if you are happy to wait until the process terminates and the system unloads automatically.
Assuming you can obtain p/invoke signatures for LoadLibrary and friends, the code looks like this:
// declare the structure of function pointers
struct DATA_API_FUNC_TAB
{
IntPtr api_init;
// more function pointers here
}
....
// load the DLL, and obtain the structure of function pointers
IntPtr lib = LoadLibrary(#"full\path\to\dll");
if (lib == IntPtr.Zero)
throw new Win32Exception();
IntPtr funcTabPtr = GetProcAddress(lib, "data_api_func_tab");
if (funcTabPtr == IntPtr.Zero)
throw new Win32Exception();
DATA_API_FUNC_TAB funcTab = (DATA_API_FUNC_TAB)Marshal.PtrToStructure(funcTabPtr, typeof(DATA_API_FUNC_TAB));
....
// declare the delegate types, note the calling convention
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate short api_init_delegate();
....
// obtain a delegate instance
api_init_delegate api_init = (api_init_delegate)Marshal.GetDelegateForFunctionPointer(funcTab.api_init, typeof(api_init_delegate));
....
// finally we can call the function
short retval = api_init();
It's plausible that the marshaller is capable of creating the delegate for you. In which case the struct would be:
struct DATA_API_FUNC_TAB
{
api_init_delegate api_init;
// more delegates here
}
In which case the Marshal.GetDelegateForFunctionPointer step would obviously not be necessary, the marshaller having already performed it on your behalf.
I've not tested any of this code, just typed it into the browser. No doubt there are a few wrinkles, but this code is intended more as a guide than as code that you could use directly.

Related

C# marshal native sized unsigned integer size_t, retrieve value via ref/out parameter

I have C# code that calls to a C function exported from native dll (DllImport) .
I want the C code to modify a value of x parameter passed from C# and to use modified value in managed code. C function has to be a void returning function. C# code:
uint x=0;
Func(x);
C code:
void Func(size_t x)
{
x=8;
}
I tried:
[DllImport("1.dll")]
public static extern void Func(size_t x);
But after the C# calls Func var x is still 0. I also tried the following C code. But it doesn't work either. What is my error?
void Func(size_t* x)
{
x=8;
}
Your example has several problems which have to be solved to get it working as expected. First of all your goal as I understand it is to retrieve value of a C type size_t which is set in a C void returning function via parameter.
First simple problem of retrieving value via parameters is solved with help of using either pointers to values in both C# and C or by using a combination of C# parameter modifier (ref or out) which would enforce passing of C# parameter as a pointer and a pointer in C. The function signatures will be as follows:
// Implementation with pointers
[DllImport("MyC.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true, EntryPoint = "Func")]
public static extern unsafe void CSharpFuncPtr(UIntPtr* x);
// Implementation with parameter modifiers - ref can be raplaced by out
[DllImport("MyC.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true, EntryPoint = "Func")]
public static extern void CSharpFuncMod(ref UIntPtr x); //
// C function implementation
void Func(size_t* x) { *x = 7; }
The second even more important problem which has to be solved during marshalling is the use of native sized unsigned integer size_t as C type. It is defined as either 32bit unsigned integer on x86 architectures or 64bit unsigned integer on x64 architectures (I do intentionally skip all other processor architectures). In .NET type system native sized integral types are missing. The workaround is to use managed unsigned pointer type UIntPtr to emulate size_t in managed type system.
.NET team is aware of this limitations and there are discussions and plans on implementing so called native integers - see: Support natural size data types in the CLR
[DllImport("MyC.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true, EntryPoint = "Func")]
public static extern void CSharpFuncNativeInt(ref nuint x);
Finally the problem which seems to be easy at the surface is not that simple after all and simple and elegant solution requires even .NET runtime and BCL libraries changes.
If you want to use pointers to and from unmanaged code, you need to use the ref qualifier.
Like:
[DllImport("1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Func(ref int x);
static void Main(string[] args)
{
int value = 0;
GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned);
Func(ref value);
handle.Free();
Console.WriteLine(value);
}
external code:
extern "C" __declspec(dllexport) void Func(int * nStatus)
{
*nStatus = 10;
}
This is because in c# you normally can't use pointers, because of the memory management (aka GC). You have to "force it" using ref-s, or unsafe code.
P.S.
It works without the GCHandle.Alloc function, but without that, there is a possibility, that while you are doing work in the unmanaged code the GC moves the value, and it gets corrupted. In this case you don't need it, but if you use a reference type instead of a value type (class instead of struct), than it becomes extremely useful.

How safe is ref when used with unsafe code?

Using Microsoft Visual C# 2010, I recently noticed that you can pass objects by ref to unmanaged code. So I tasked myself with attempting to write some unmanaged code that converts a C++ char* to a a C# string using a callback to managed code. I made two attempts.
Attempt 1: Call unmanaged function that stores a ref parameter. Then, once that function has returned to managed code, call a another unmanaged function that calls a callback function that converts the char* to a managed string.
C++
typedef void (_stdcall* CallbackFunc)(void* ManagedString, char* UnmanagedString);
CallbackFunc UnmanagedToManaged = 0;
void* ManagedString = 0;
extern "C" __declspec(dllexport) void __stdcall StoreCallback(CallbackFunc X) {
UnmanagedToManaged = X;
}
extern "C" __declspec(dllexport) void __stdcall StoreManagedStringRef(void* X) {
ManagedString = X;
}
extern "C" __declspec(dllexport) void __stdcall CallCallback() {
UnmanagedToManaged(ManagedString, "This is an unmanaged string produced by unmanaged code");
}
C#
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void StoreCallback(CallbackFunc X);
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void StoreManagedStringRef(ref string X);
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void CallCallback();
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackFunc(ref string Managed, IntPtr Native);
static void Main(string[] args) {
string a = "This string should be replaced";
StoreCallback(UnmanagedToManaged);
StoreManagedStringRef(ref a);
CallCallback();
}
static void UnmanagedToManaged(ref string Managed, IntPtr Unmanaged) {
Managed = Marshal.PtrToStringAnsi(Unmanaged);
}
Attempt 2: Pass string ref to unmanaged function that passes the string ref to the managed callback.
C++
typedef void (_stdcall* CallbackFunc)(void* ManagedString, char* UnmanagedString);
CallbackFunc UnmanagedToManaged = 0;
extern "C" __declspec(dllexport) void __stdcall StoreCallback(CallbackFunc X) {
UnmanagedToManaged = X;
}
extern "C" __declspec(dllexport) void __stdcall DoEverything(void* X) {
UnmanagedToManaged(X, "This is an unmanaged string produced by unmanaged code");
}
C#
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void StoreCallback(CallbackFunc X);
[DllImport("Name.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void DoEverything(ref string X);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackFunc(ref string Managed, IntPtr Unmanaged);
static void Main(string[] args) {
string a = "This string should be replaced";
StoreCallback(UnmanagedToManaged);
DoEverything(ref a);
}
static void UnmanagedToManaged(ref string Managed, IntPtr Unmanaged) {
Managed = Marshal.PtrToStringAnsi(Unmanaged);
}
Attempt 1 doesn't work but attempt 2 does. In attempt 1 it seems that as soon as the unmanaged code returns after storing the ref, the ref becomes invalid. Why is this happening?
Given the outcomes of attempt 1, I have doubts that attempt 2 will work reliably. So, how safe is ref on the unmanaged side of code when used with unmanaged code? Or in other words, what won't work in unmanaged code when using ref?
Things I'd like to know are are:
What exactly happens when objects are passed using ref to unmanaged code?
Does it guarantee that the objects will stay at their current position in memory while the ref is being used in unmanaged code?
What are the limitations of ref (what can't I do with a ref) in unmanaged code?
A complete discussion of how p/invoke works is beyond the proper scope of a Stack Overflow Q&A. But briefly:
In neither of your examples are you really passing the address of your managed variable to the unmanaged code. The p/invoke layer includes marshaling logic that translates your managed data to something usable by the unmanaged code, and then translates back when the unmanaged code returns.
In both examples, the p/invoke layer has to create an intermediate object for the purpose of marshaling. In the first example, this object is gone by the time you call the unmanaged code again. Of course in the second example, it's not, since all of the work happens all at once.
I believe that your second example should be safe to use. That is, the p/invoke layer is smart enough to handle ref correctly in that case. The first example is unreliable because p/invoke is being misused, not because of any fundamental limitation of ref parameters.
A couple of additional points:
I wouldn't use the word "unsafe" here. Yes, calling out to unmanaged code is in some ways unsafe, but in C# "unsafe" has a very specific meaning, related to the use of the unsafe keyword. I don't see anything in your code example that actually uses unsafe.
In both examples, you have a bug related to your use of the delegate passed to unmanaged code. In particular, while the p/invoke layer can translate your managed delegate reference to a function pointer that unmanaged code can use, it doesn't know anything about the lifetime of the delegate object. It will keep the object alive long enough for the p/invoked method call to complete, but if you need it to live longer than that (as would be the case here), you need to do that yourself. For example, use GC.KeepAlive() on a variable in which you've stored the reference. (You likely can reproduce a crash by inserting a call to GC.Collect() between the call to StoreCallback() and the later call to unmanaged code where the function pointer would be used).

Calling function in C dll from C# which returns somekind of pointer to function pointer

I have an dll written in C (no access to the source code) which I wish to call from C#. If the dll used simple types I would know how to handle it via PInvoke, but it doesn't :(
The function in the dll I'm trying to call takes no parameters so the problem is how to handle the return. I have some example C code which calls the function which I liked to recreate in C#. As I understand it the return type is a pointer to a function pointer, is this correct? The return from the function should also later be passed back to other functions in the dll.
Any help is greatly appreciated :)
/* C code */
typedef const struct simModel* (*ModelFunc)(void);
int ret=0;
HINSTANCE hInst = 0;
ModelFunc f=0;
const struct simModel*model =0;
if (!(hInst=LoadLibrary("model.dll"))) {
return 1;
}
if (!(f=(ModelFunc)GetProcAddress(hInst,"simModelFunctions"))) {
ret=1;
} else if (!(model=f())) {
ret=1;
} else {
/* Do stuff */
}
The simModelFunctions function returns a pointer to simModel structure (a data type).
The code you show calls the function by finding its address dynamically, which is why it has a function pointer. This pointer does not come from the function itself.
In C# you can simply declare it with DllImport from model.dll. E.g.
[DllImport("model.dll", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
private static IntPtr simModelFunctions();
Then you can use Marshal.PtrToStructure if you need to examine the contents of the structure, or just pass the returned IntPtr to other functions without bothering what's inside.

Invoke a C DLL function to marshal a string from a type defined char

This is my first attempt at creating a C# wrapper to a C lib. The SDK is 3rd party and outside my control:
sdk_defines.h
#ifndef SDK_CHAR_T
#define SDK_CHAR_T
typedef char sdk_char_t;
#endif /* SDK_CHAR_T */
#ifndef SDK_CSTR_T
#define SDK_CSTR_T
typedef const sdk_char_t* sdk_cstr_t;
#endif /* SDK_CSTR_T */
sdk.h
sdk_cstr_t SDK_API
sdk_get_version(void);
My C# wrapper:
[DllImport("sdk.dll", CharSet = CharSet.Ansi)]
private static extern string sdk_get_version();
Any call to sdk_get_version causes a crash, no exception. I have a feeling it's the return type, but how do I properly marshal it in C#?
If you return as string, then the marshaller will call CoTaskMemFree on the pointer that is returned. I expect that's what's happening to you and is why your code fails. Looking at that API it seems most likely that the pointer that is returned points to a string literal in the DLL, certainly not something allocated with CoTaskMemAlloc.
So, you are going to need to return that as an IntPtr and then convert to string using Marshal.PtrToStringAnsi.
So you need it like this:
[DllImport("sdk.dll")]
private static extern IntPtr sdk_get_version();
....
IntPtr ptr = sdk_get_version();
string version = Marshal.PtrToStringAnsi(ptr);
Before you go much further you need to work out what SDK_API is. Is it stdcall or is it cdecl? It makes no difference for this no-parameter function, but before long you'll be passing parameters, and you'll need to know.

How do I marshal a pointer to an array of pointers to structures from managed to unmanaged code?

I'm trying to write plugin dll which has to implement the following function:
int GetFunctionTable(FuncDescStruct **ppFunctionTable);
So my plugin code in C# declares this:
public static unsafe int GetFunctionTable(IntPtr functionTablePtr);
This function will be called and expected to fill functionTablePtr with pointer to array of structs describing set of callback functions.
In plain C/C++ it looks something like:
// declare func table
// VExampleF1, VExampleF2 - are function pointers
FuncDescStruct funcTable[] = {
"ExampleF1", { VExampleF1, 0, 0, 0, 0, NULL }, //filling descriptions.
"ExampleF2", { VExampleF2, 1, 0, 1, 0, NULL }
};
int GetFunctionTable(FuncDescStruct **ppFunctionTable)
{
*ppFunctionTable = funcTable; // how to do this correctly in C#?
// must return the number of functions in the table
return funcTableSize;
}
I'm trying to do the following:
static unsafe FunctionTag[] funcTable;
static List<IntPtr> allocatedMemory;
public static unsafe int GetFunctionTable(IntPtr functionTablePtr)
{
//create just one test callback description
funcTable = new FunctionTag[1];
funcTable[0].Name = "VExampleF1";
funcTable[0].Description.Function = VExampleF1;
funcTable[0].Description.ArrayQty = 0;
funcTable[0].Description.FloatQty = 0;
funcTable[0].Description.StringQty = 0;
funcTable[0].Description.DefaultQty = 0;
funcTable[0].Description.DefaultValues = null;
// saving allocated memory for further cleanup
allocatedMemory = new List<IntPtr>();
int intPtrSize = Marshal.SizeOf(typeof(IntPtr));
IntPtr nativeArray = Marshal.AllocHGlobal(intPtrSize * funcTable.Length);
for (int i = 0; i < funcTable.Length; i++)
{
IntPtr nativeFD = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(FunctionTag)));
allocatedMemory.Add(nativeFD);
Marshal.StructureToPtr(funcTable[i], nativeFD, false);
Marshal.WriteIntPtr(nativeArray, i * intPtrSize, nativeFD);
}
Marshal.WriteIntPtr(functionTablePtr, nativeArray);
return funcTable.Length;
}
Such code doesn't work, and the question is how to send a pointer to array of managed structs for use by unmanaged code? In which direction should I go?
We've been doing quite a lot of this sort of thing over the last couple of years.
We use a mixed-mode 'bridge' assembly to manage mapping function calls and marshalling data between managed and unmanaged environments. We often use a 'mixed-mode' class to wrap a managed class, providing a native interface for calling it's functionality.
Let's consider your problem. You could write GetFunctionTable in managed c++. It can call some managed c# code to get the function information in a managed struct, and then 'marshall' it into the native struct.
In (c#) a managed version of GetFunctionTable function:
delegate void FunctionDelegate();
public struct FuncDescStructManager
{
public string Name;
public FunctionDelegate Function;
//...
}
public static List<FuncDescStructManager> GetFunctionTableManaged()
{
List<FuncDescStructManager> list = new List<FuncDescStructManager>();
list.Add(new FuncDescStructManaged () {"ExampleF1", VExampleF1});
return list;
}
In the mixed-mode bridge assembly you can implement the native function GetFunctionTable,
calling the managed function and marshalling the data:
int GetFunctionTable(FuncDescStruct **ppFunctionTable)
{
// Call the managed function
List<FuncDescStructManaged>^ managedList = GetFunctionTableManaged();
nativeArray = malloc(managedList.Length * sizeof(FuncDescStruct));
int i=0;
foreach (FuncDescStructManaged managedFunc in managedList)
{
// Marshall the managed string to native string could look like this:
stringPtr = Marshal::StringToHGlobalUni(managedFunc.Name);
nativeArray[i].Name = ((wchar_t*)stringPtr.ToPointer());
Marshal::FreeHGlobal(stringPtr);
// Marshall a delegate into a native function pointer using a
// wrapper class:
WrapDelegateAsPtr funcPtr = new WrapDelegateAsPtr(managedFunc.Function);
// funcPtr will need to be deleted by caller
nativeArray[i].Function = funcPtr.NativeFunction;
i++;
}
return i;
}
// Mixed mode wrapper class
// Member is a reference to a managed delegate.
// Because we need to reference this from native code, the wrapped
// delegate will be stored as a void*.
class WrapDelegateAsFPtr
{
public:
WrapDelegateAsNativeFunctionPointer(FunctionDelegate _delegate)
{
delegate = _delegate;
// Tell the garbage handler not to remove the delegate object yet
GCHandle gch = GCHandle::Alloc(svgContents);
managedDelegatePtr = GCHandle::ToIntPtr(gch).ToPointer();
}
~WrapDelegateAsNativeFunctionPointer
{
// Tell the garbage collector we are finished with the managed object
IntPtr temp(managedDelegatePtr;);
GCHandle gch = static_cast<GCHandle>(temp);
gch.Free();
}
void NativeFunction()
{
}
private:
void* managedDelegatePtr;
}
Hope this helps - Any questions just ask!
THis is a rather belatedd answer, but I have come up against exactly the same problem. I have implmented a DATA PLUGIN using Kostya's framework, and got it to work perfectly, then trying to implmement an AFL plugin, I ran into the problem as per above. I have managed to get itworking without using a C++ rapper class.
The problem is with the function pointer/reference/address that is passed from withing the FUnctionTable. AS these functions have been dclared as STATIC for EXPORT purposes, they are incompatible with the C++ delegate implmentation in the GETFUNCTIONTABLE method. IF you ddo the following , it should work:-
Add the 2 signatures:-
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool SetDllDirectory(string lpPathName);
the function reference definition in the GetFunctionTable structure must be changed to:
IntPtr Function;
Add the following statements to get the exported function address:-
IntPtr dllHandle = LoadLibrary(fullPath);
IntPtr fptr = GetProcAddress(dllHandle, "VfmExample1");
and lastly initialize the function variable in the GetFunctionTable structure , e.g.
functable[0].Description.function = fptr;
and that should do it
You have to use the fixing construct to fix the buffer in place, because the C# GC reserves the right to move it around if you don't, invalidating the pointer. I don't know how to fix a buffer indefinitely. You're going to have to worry about how that memory is managed, too.

Categories