In a winapi function I have to pass the address of the callback function
that function has to use.
So I declared a unsafe class and everything, but bool* addressofmyfunction = &GetHandle;
just won't compile!
Please help me or give me an alternative to passing the address like this.
In .NET delegates are used to store pointers to functions. For example if you have the following function:
public int GetHandle(int arg1)
{
return arg1 + 10;
}
it's address will be defined like so:
Func<int, int> addressOfMyFunction = GetHandle;
and you can invoke it like that:
int result = addressOfMyFunction(50);
bool* addressofmyfunction = &GetHandle won't compile in C or C++ either (the correct syntax would be bool (*addressofmyfunction)() = &GetHandle), but you can't do like that. I'm not an expert in interop, but I think you have to use Marshal.GetFunctionPointerForDelegate.
Function pointers are represented by delegates in C#. Since methods aren't moved by the garbage collector, you don't need to pin them (or use unsafe code) to pass them to a Win32 API function.
Example:
using System;
using System.Runtime.InteropServices;
public delegate bool CallBack(int hwnd, int lParam);
public class EnumReportApp {
[DllImport("user32")]
public static extern int EnumWindows(CallBack x, int y);
public static void Main()
{
CallBack myCallBack = new CallBack(EnumReportApp.Report);
EnumWindows(myCallBack, 0);
}
public static bool Report(int hwnd, int lParam) {
Console.Write("Window handle is ");
Console.WriteLine(hwnd);
return true;
}
}
There is a similar example for EnumThreadWindows on pinvoke.net.
Related
let say we have following code in a dll written in C-lang, where i try to map some functions defined in the dll as functionpointers, map to their actual functions, i follow following link to get till here
https://learn.microsoft.com/en-us/dotnet/framework/interop/marshaling-different-types-of-arrays
Dlltest.h
typedef struct VersionInfo
{
UINT uMajor;
UINT uMinor;
UINT uMRevision;
} STRUCT_VERSION_INFO;
typedef struct DllTestFPStruct
{
int(*Close) (void);
int(*Init) (STRUCT_VERSION_INFO *sVersInfo);
int(*RegisterClient) (int id);
} STRUCT_DLL_TEST_FP_STRUCT;
typedef struct DllTestMgr
{
STRUCT_DLL_TEST_FP_STRUCT *psItf;
int iDummy;
} STRUCT_DLL_TEST_MGR;
extern "C"
{ __declspec(dllexport) void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP); }
Dlltest.c
static int Close(void);
static int Init(STRUCT_VERSION_INFO *sVersInfo);
static int RegisterClient(int id);
STRUCT_DLL_TEST_FP_STRUCT sFP =
{
&Close,
&Init,
&RegisterClient,
};
DLLTESTC_API void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP)
{ psFP->psItf = &sFP; }
static int Close(void)
{ printf("Closed called.\n"); }
static int Init(STRUCT_VERSION_INFO *sVersInfo)
{ printf("Init called.\n");}
static int RegisterClient(STRUCT_VERSION_INFO *sVersInfo)
{ printf("RegisterClient called.\n");}
Now i want to write a c# application which uses this DLL, specially it should make use of the "GetDllTestFP"-Function which maps the functionpointers to their actuall function. right now my C#-Application is as follow:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int FP_DLL_TEST_CLOSE(ref VersionInfo sVersInfo);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int FP_DLL_TEST_INIT(ref VersionInfo sVersInfo);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int FP_DLL_TEST_RC(ref VersionInfo sVersInfo);
[StructLayout(LayoutKind.Sequential)]
public struct DllTestFPStruct
{
public FP_DLL_TEST_CLOSE Close;
public FP_DLL_TEST_INIT Init;
public FP_DLL_TEST_RC RegisterClient;
}
[StructLayout(LayoutKind.Sequential)]
public struct DllTestMgr
{
public IntPtr psItf;
public int iDummy;
}
[DllImport("DllTestC.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern void GetDllTestFP(ref DllTestMgr ps);
static void Main(string[] args)
{
VersionInfo vInfo = new VersionInfo();
DllTestFPStruct dllFPs = new DllTestFPStruct();
DllTestMgr dllTest = new DllTestMgr();
IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(dllFPs));
Marshal.StructureToPtr(dllFPs, buffer, false);
dllTest.psItf = buffer;
GetDllTestFP(ref dllTest); // Funtionpointers are not mapped, still null
dllFPs.Close(ref vInfo);
}
The problem is, that the functions do not get mapped to their actuall functions in the dll.
Any idea how can i achieve my goal?
Thanks
The C# code is:
DllTestMgr dllTest = new DllTestMgr();
GetDllTestFP(ref dllTest);
DllTestFPStruct dllFPs = (DllTestFPStruct)Marshal.PtrToStructure(dllTest.psItf, typeof(DllTestFPStruct));
VersionInfo vInfo = new VersionInfo();
dllFPs.Close(ref vInfo);
You don't need to allocate dllTest.psItf becase in GetDllTestFP you do:
DLLTESTC_API void GetDllTestFP(STRUCT_DLL_TEST_MGR *psFP)
{
psFP->psItf = &sFP;
}
So you copy the address of sFP.
Note that in general this is a bad idea, because you are giving to the "client" direct access to your data (the sFP struct). The alternative is that the client passes the memory (as you wrote before) and then you do:
(*psFP->psItf) = sFP;
(but then remember to free the allocated memory!)
Third alternative, the C-side allocates a block of memory through a shared allocator (one that can be used by C#, so no malloc/new here) and then the C# has to deallocate it.
wrong solution is
STRUCT_DLL_TEST_FP_STRUCT sFP2 = sFP;
psFP->psItf = &sFP2;
The lifetime of sFP2 ends when the method returns. psFP->psItf is now pointing to a piece of stack that doesn't exist anymore. don't do it!
Ah... as written by #Hans Passant, depending on who allocates the memory, the GetDllTestFP can be ref or out. If the memory is allocated by C# then it must be ref, if it isn't allocated (as is now) or is allocated by C++, then out is ok and you'll save on the marshaling in one direction.
I have an unmanaged DLL that exports only a C style factory method that returns a new instance of a class (simplified here to look simple).
hello.h
#if defined(HWLIBRARY_EXPORT) // inside DLL
# define HWAPI __declspec(dllexport)
#else // outside DLL
# define HWAPI __declspec(dllimport)
#endif
struct HelloWorld{
public:
virtual void sayHello() = 0;
virtual void release() = 0;
};
extern "C" HWAPI HelloWorld* GetHW();
hello.cpp
#include "hello.h"
struct HelloWorldImpl : HelloWorld
{
void sayHello(){
int triv;
std::cout<<"Hello World!";
std::cin>>triv;
};
void release(){
this->HelloWorldImpl::~HelloWorldImpl();
};
HelloWorld* GetHW(){
HelloWorld* ptr = new HelloWorldImpl();
return ptr;
};
Now, I can use dllimport to access GetHW() but is there a way to access the member functions of the returned 'struct'... ie, sayHello and release?
I was also stuck with the same problem. This question was asked a while before. I commented to it for any better solution but didn't get any reply yet. So, reposting it.
When i googled, able to find out two solutions.
Solution1: Expose all the member functions in the C-style for the existing dll. Which i cant do, as it is a 3rd party dll.
Solution2: Write a managed C++ dll exposing the functionality of native C++ dll, which later can be used in your C# dll. Here many classes/functions are present. So, creating would take most of the time.
i got the above solutions from the link below.
How To Marshall
Please let me know if there is any better solution other than the above two solutions?
i have the source code for C++ solution. But what i though was not to touch C++ dll. If there is any possibility to do it in C#, it would be great.
If there is no alternative, i need to follow any one of the specified two solutions.
The C++ code is using the way abstract classes are implemented by the Visual C++ compiler. http://blogs.msdn.com/b/oldnewthing/archive/2004/02/05/68017.aspx. This memory layout is "fixed" because it is used for implementing COM interfaces. The first member of the struct in memory will be a pointer to a vtable containing the function pointers of your methods. So for a
struct HelloWorldImpl : public HelloWorld
{
public:
int value1;
int value2;
}
the "real" layout in memory would be:
struct HelloWorldImpl
{
HelloWorldVtbl *vtbl;
int value1;
int value2;
}
where vtbl would be:
struct HelloWorldVtbl
{
void *sayHello;
void *release;
}
Just for the sake of doing a complete response, I'm writing the example for this signatures:
struct HelloWorld {
public:
virtual int sayHello(int v1, int v2, int v3) = 0;
virtual void release() = 0;
};
C# code:
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetHW();
[StructLayout(LayoutKind.Sequential)]
struct HelloWorldVtbl
{
public IntPtr sayHello;
public IntPtr release;
}
Your functions are void Func(void) or int Func(int, int, int), but in truth they have a hidden parameter, this, so you can write them as:
int sayHello(HelloWorld*, int, int, int);
void release(HelloWorld*);
so in C# the delegate is
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate int Int32MethodInt32Int32Int32(IntPtr ptr, int v1, int v2, int v3);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void VoidMethodVoid(IntPtr ptr);
Then you can use
IntPtr ptr = GetHW();
IntPtr vtbl = Marshal.ReadIntPtr(ptr, 0);
HelloWorldVtblhw = (HelloWorldVtbl)Marshal.PtrToStructure(vtbl, typeof(HelloWorldVtbl));
Int32MethodInt32Int32Int32 sayHello = (Int32MethodInt32Int32Int32)Marshal.GetDelegateForFunctionPointer(hw.sayHello, typeof(Int32MethodInt32Int32Int32));
int res = sayHello(ptr, 1, 2, 3);
Console.WriteLine(res);
VoidMethodVoid release = (VoidMethodVoid)Marshal.GetDelegateForFunctionPointer(hw.release, typeof(VoidMethodVoid));
release(ptr);
I'm using a native DLL that is called out of my C# application. One of the DLL-functions is defined like this:
int set_line(const int width,fct_line_callback callback)
fct_line_callback itself is defined as
typedef int (*fct_line_callback)(double power,void *userData);
So how can I use this function out of my C#-application? Is there a way to define a C# method to be used as callback-function for this DLL-call?
Thanks!
You have to declare a delegate type that matches the native function pointer. It probably should look like this:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int fct_line_callback(double power, IntPtr userdata);
Now you can write the pinvoke declaration:
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
extern static int set_line(int width, fct_line_callback callback);
If the callback can only be made while set_line() is executing then calling the native function is simple:
public void SetLine(int width) {
set_line(width, MyCallback);
}
private void MyCallback(double power, IntPtr userdata) {
// etc...
}
However, if the callback can be made after set_line() is executed, in other words when the native code stores the function pointer, then you have to make sure that the garbage collector cannot collect the delegate object. Simplest way to do so is by storing the object in a static variable:
static class Wrapper {
private static fct_line_callback callback = MyCallback;
public static void SetLine(int width) {
set_line(width, callback);
}
private static int MyCallback(double power, IntPtr userdata) {
// etc...
}
}
I have some C code which will be called from C# using P/Invoke. I am trying to define an C# equivalent for this C function.
SomeData* DoSomething();
struct SomeData
{
...
}
How do I import this C method to C#? I am having trouble defining the return type of the function.
EDIT:
i had a bunch of functions to import. This is one which had me stuck.
[DllImport("SomeDll.dll")]
public static extern IntPtr DoSomething();
I thought about using IntPtr, even if its the right way what after that?
I'm not quite sure I understand your question but I'll give a shot at answering it. You need to define the structure that is being returned from your C function and use Marshal.PtrToStructure to use the returned structure.
[DllImport("SomeDll.dll")]
public static extern IntPtr DoSomething();
public struct SomeData
{
//...
}
//code to use returned structure
IntPtr result = DoSomething();
SomeData structResult = (SomeData)Marshal.PtrToStructure(result, typeof(SomeData));
I am guessing that what you are trying to achieve is the following:
Your C/C++ native method takes no parameters and returns a pointer to a structure.
The C# equivalent is to return an IntPtr (pointer).
The problem is that you cannot resolve the IntPtr to the structure in C#
...research this:
Marshal.PtrToStructure(IntPtr, Type)
http://msdn.microsoft.com/en-us/library/4ca6d5z7.aspx
You can wrap your code up like so
public static class UnsafeNativeMethods
{
[DllImport("SomeDll.dll")]
private static extern IntPtr DoSomething(); //NO DIRECT CALLS TO NATIVE METHODS!!
public static SomeData SafeDoSomething()
{
try
{
return (SomeData)Marshal.PtrToStructure(DoSomething(), typeof(SomeData));
}
catch(Exception ex)
{
//handle exception
}
}
}
I'm trying to call functions of a C DLL.
But I got a StackOverflowException so I think something is wrong with the function as parameter.
In detail it looks like this.
C DLL (header file):
typedef struct
{
MyType aType; /* message type */
int nItems; /* number of items */
const MyItems *lpItem; /* pointer to array of items */
} MyStruct;
typedef void (__stdcall *MyCbFunc) (HWND, const MyStruct *);
API(BOOL) RegisterCbFunc (ARGS, MyCbFunc);
In C# I tried this:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MyStruct
{
MyType aType;
int nItems;
MyItems[] lpItem;
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackDelegate(MyStruct mStruct);
[DllImport("MY.dll", CallingConvention=CallingConvention.StdCall)]
private static extern int RegisterCbFunc(IntPtr hWnd, Delegate pCB);
public static void MyCbFunc(MyStruct mStruct)
{
// do something
}
static void Main(string[] args)
{
CallbackDelegate dCbFunc = new CallbackDelegate(MyCbFunc);
int returnValue = RegisterCbFunc(IntPtr.Zero, dCbFunc);
// here, returnValue is 1
}
This runs as long until the DLL calls the callback function. Then I got an error:
An unhandled exception of type 'System.StackOverflowException' occurred in Microsoft.VisualStudio.HostingProcess.Utilities.dll
Thanks for help.
ANSWER:
I don't know why, but there was an answer which is now deleted?!
I try to recover it. The solution was to use call by reference instead of call by value for the function parameter.
public delegate void CallbackDelegate(ref MyStruct mStruct);
Your C function is expecting a pointer to a MyStruct, but you're telling the C# that it wants a pointer to a function. The difference between a function and a struct is... significant. Perhaps try something like
[DllImport("MY.dll", CallingConvention=CallingConvention.StdCall)]
private static extern int RegisterCbFunc(IntPtr hWnd, Delegate pCB);
static void Main(string[] args)
{
MyStruct mStruct;
int returnValue = RegisterCbFunc(IntPtr.Zero, mStruct);
}
If your C function is filling in the lpItem member of the MyStruct with something it allocates itself, I've got no idea what happens next, but at least it's not going to be trying to overwrite your code.