Asynchronous and RealTime Connection in DLLImport [duplicate] - c#

in my next project I want to implement a GUI for already existing code in C++.
My plan is to wrap the C++ part in a DLL and to implement the GUI in C#. My problem is that I don't know how to implement a callback from the unmanaged DLL into the manged C# code. I've already done some development in C# but the interfacing between managed and unmanaged code is new to me. Can anybody give me some hints or reading tips or a simple example to start from? Unfortunatly I could not find anything helpful.

You don't need to use Marshal.GetFunctionPointerForDelegate(), the P/Invoke marshaller does it automatically. You'll need to declare a delegate on the C# side whose signature is compatible with the function pointer declaration on the C++ side. For example:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
class UnManagedInterop {
private delegate int Callback(string text);
private Callback mInstance; // Ensure it doesn't get garbage collected
public UnManagedInterop() {
mInstance = new Callback(Handler);
SetCallback(mInstance);
}
public void Test() {
TestCallback();
}
private int Handler(string text) {
// Do something...
Console.WriteLine(text);
return 42;
}
[DllImport("cpptemp1.dll")]
private static extern void SetCallback(Callback fn);
[DllImport("cpptemp1.dll")]
private static extern void TestCallback();
}
And the corresponding C++ code used to create the unmanaged DLL:
#include "stdafx.h"
typedef int (__stdcall * Callback)(const char* text);
Callback Handler = 0;
extern "C" __declspec(dllexport)
void __stdcall SetCallback(Callback handler) {
Handler = handler;
}
extern "C" __declspec(dllexport)
void __stdcall TestCallback() {
int retval = Handler("hello world");
}
That's enough to get you started with it. There are a million details that can get you into trouble, you are bound to run into some of them. The much more productive way to get this kind of code going is writing a wrapper in the C++/CLI language. That also lets you wrap a C++ class, something you can't do with P/Invoke. A decent tutorial is available here.

P/Invoke can handle marshaling a managed delegate to a function pointer. So if you expose API's that register a call back function from your DLL and in C# pass a delegate to that function.
There is an example on MSDN of doing this with the EnumWindows function. In that article be careful to pay attention to the line in point 4 that states:
If, however, the callback function can
be invoked after the call returns, the
managed caller must take steps to
ensure that the delegate remains
uncollected until the callback
function finishes. For detailed
information about preventing garbage
collection, see Interop Marshaling
with Platform Invoke.
What that is saying is that you need to make sure that your delegate isn't garbage collected until after the managed code is done calling it by either keeping a reference to it in your code, or pinning it.

See Marshal.GetFunctionPointerForDelegate, which will give you a function pointer for calling managed (i.e. C# code) from unmanaged code.

Have a look at this, Marshal.GetDelegateForFunctionPointer?

Related

PinvokeStackImbalance occured. This exception is thrown but i have no idea what the error is?

The exception:
Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'D:\UI_still_in_progress\user_interface\bin\Debug\WindowsFormsApplication1.vshost.exe'.
Basically my application has a background real time process in c++ which communicates with a micro-processor. Ive set up a c++ dll file which allows me to pass data from the c++ application and c# UI in real time.
My problem is that I have to create a finite state machine to make sure the physical device and c++ app are all doing what they should be based on whats going on in the UI. so my goal is to pass simple integers representing the states from c# to c++.
The real time data is passing from c++ to c# with no issues using the following implementation:
c++ .h file snippet:
extern "C" __declspec (dllexport) int grabx();
extern "C" __declspec (dllexport) void setFSMstate(int s);
C++ .cpp file snippet:
int grabx()
{
return x0;
}
void setFSMstate(int s)
{
state = s;
}
c# class
public class MyDllMethods {
[DllImport("dllTESTER.dll")]
public static extern int grabx();
[DllImport("dllTESTER.dll")]
public static extern void setFSMstate(int s);
}
c# method calls
xx = MyDllMethods.grabx();
MyDllMethods.setFSMstate(2);
The grabx() function works fine and i can read the x value from the device in real time. When my UI moves to a new screen i attempt to change the state in every application by passing a 2 into setFSMstate(). When this method is called the exception is thrown.
I am quite new to P/Invoke so if there is anything I missed please help out. I may have marshaled it wrong but im confident that type int is the same in c# and c++?
The problem you're running into is a calling convention mismatch. Calling conventions specify how parameters are passed to functions, and how their return values are passed back to the caller. Your C++ functions are being declared with an implicit calling convention of __cdecl, but P/Invoke's default calling convention is __stdcall.
To fix this, you just have to change your P/Invoke configuration:
[DllImport("dllTESTER.dll", CallingConvention = CallingConvention.Cdecl)]
(The reason you didn't have any problems with your first method is that it doesn't have any parameters—__cdecl and __stdcall pass parameters differently, but they both specify that integer return values are stored in the EAX register.)

declspec and stdcall vs declspec only

I'm a new person to C++ dll import topic and may be my question is very easy but I can not find it on google.
I have a very simple C++ win32 dll:
#include <iostream>
using namespace std;
extern "C"
{
__declspec(dllexport) void __stdcall DisplayHellowFromDLL()
{
cout<<"Hi"<<endl;
}
}
When I call this method from C# I do not have any problem, here is C# code
namespace UnmanagedTester
{
class Program
{
[DllImport(#"C:\CGlobalDll")]
public static extern void DisplayHellowFromDLL();
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
DisplayHellowFromDLL();
}
}
}
As I expected the output is: "This is C# program" "Hi".
Now if I change the declaration of C function as:
__declspec(dllexport) void DisplayHellowFromDLL()
without __stdcall, I do not have any problem as well, and the question is:
When do I really need __declspec(dllexport) TYPE __stdcall and when I can use only __declspec(dllexport) TYPE ?
Thanks a lot.
You can think of it like this:
__declspec(dllexport) declares your function as a public function that your DLL exports;
__stdcall is a rather low-level detail that refers to the "calling convention" adopted by that function; specifically, __stdcall means that the callee cleans the stack;
alternative to __stdcall is __cdecl, which means: the caller cleans the stack.
__cdecl is the "natural" C calling convention; it supports the definition of vararg functions (like printf).
__stdcall is the default calling convention for DLL functions, so you don't need specify it if you are only going to call those functions through their DLL API.
This should explain what you are observing.
It works by accident because the function doesn't take any arguments. As soon as you do this on a function that does take arguments you'll start running out of luck. The call will leave the stack imbalanced, very unhealthy. You'd get the pInvokeStackImbalance MDA warning when you debug. An imbalanced stack can otherwise go unnoticed for a while, it tends to crash your program in the Release build.
You need to specify the calling convention if you compile the calling code with some other convention. Otherwise the default will work.
Ilya, you can also set the default calling convention in Project Properties -> Configuration Properties -> C/C++ -> Advanced -> Calling Convention.
If the default calling convention in your project is already set to __stdcall (/Gz), then adding __std

C++/CLI wrapper for C dll

So I have this C .dll source code which I want to use in my C# application. Instead of doing bunch of DllImports I've decided to write a wrapper for it in C++/CLI.
My C function takes a pointer to a struct with 4 callback functions in it:
typedef struct
{
PFN_IN readFp;
PFN_OUT writeFp;
}OPEN_ARGS;
C++/CLI shares the same .h file, therefore uses the same typedef.
C# code has it's own definition of this structure and delegates for CBs, because I can't attach .h to C# project.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate Int32 PFN_OUT(IntPtr arg, IntPtr pSrc, Int32 len);
[StructLayout(LayoutKind.Sequential)]
public struct OPEN_ARGS
{
public PFN_IN readFp;
public PFN_OUT writeFp;
};
So, when I add my C++/CLI dll explicitly to C# project references, the compliler wouldn't accept calls to C++/CLI functions saying
"Error 2 Argument 2: cannot convert from 'WrapperTest.Program.OPEN_ARGS' to 'SAR_OPEN_ARGS'"
But if I include the C++/CLI dll implicitly like that
[DllImport("Wrapper.dll", CharSet = CharSet.Auto, EntryPoint = "?CLIOpen##YAHHUOPEN_ARGS###Z")]
public static extern int CLIOpen(int a, OPEN_ARGS args);
It will work just fine.
So is there a way to tell C# compiler to ignore this type cast error, or may be other way to wrap C code functions?
EDIT: cleaned up variable names for better readabiltiy
What if you did this another way. Since you have a C++/CLI DLL handling interop duties between the C DLL and the C# assembly, you could expose an equivalent API, only using more .NET-like concepts.
For example, instead of exposing the struct with function pointers, you could expose a class that has three events. The C# assembly would add handlers for those events. Inside the C++ DLL, it would use the function pointers that the C DLL expects, but their implementation would fire the .NET events that the C# assembly is handling.
This would provide a much better experience using the DLL on the C# side, and likely get rid of the interop compiler errors that you're encountering.
Please consider using SWIG to generate the wrapper code for all your pinvoke.
http://www.swig.org/Doc1.3/CSharp.html
So for managed C++, you can use the #pragma managed/unmanaged compiler directives instead of pInvoke, which it looks like you are using. Then you can compile managed and native code together into the same assembly, even the same CPP file.
Then you could do something like:
#pragma managed
// include your native headers here
#include "foo.h" // whatever you call it.
#using <System.dll> // what ever else you need here...
// Have to wrap a function in a class, since .NET doesn't allow free standing functions.
public ref class foo
{
public static int sarCLIOpen(int a, SARWrapperTest::Program::SAR_OPEN_ARGS args)
{
// do something to convert your managed args to native args.
::SAR_OPEN_ARGS native_args = ...
// then call your native function
return sarCLIOpen(a, native_args );
}
};

Howto implement callback interface from unmanaged DLL to .net app?

in my next project I want to implement a GUI for already existing code in C++.
My plan is to wrap the C++ part in a DLL and to implement the GUI in C#. My problem is that I don't know how to implement a callback from the unmanaged DLL into the manged C# code. I've already done some development in C# but the interfacing between managed and unmanaged code is new to me. Can anybody give me some hints or reading tips or a simple example to start from? Unfortunatly I could not find anything helpful.
You don't need to use Marshal.GetFunctionPointerForDelegate(), the P/Invoke marshaller does it automatically. You'll need to declare a delegate on the C# side whose signature is compatible with the function pointer declaration on the C++ side. For example:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
class UnManagedInterop {
private delegate int Callback(string text);
private Callback mInstance; // Ensure it doesn't get garbage collected
public UnManagedInterop() {
mInstance = new Callback(Handler);
SetCallback(mInstance);
}
public void Test() {
TestCallback();
}
private int Handler(string text) {
// Do something...
Console.WriteLine(text);
return 42;
}
[DllImport("cpptemp1.dll")]
private static extern void SetCallback(Callback fn);
[DllImport("cpptemp1.dll")]
private static extern void TestCallback();
}
And the corresponding C++ code used to create the unmanaged DLL:
#include "stdafx.h"
typedef int (__stdcall * Callback)(const char* text);
Callback Handler = 0;
extern "C" __declspec(dllexport)
void __stdcall SetCallback(Callback handler) {
Handler = handler;
}
extern "C" __declspec(dllexport)
void __stdcall TestCallback() {
int retval = Handler("hello world");
}
That's enough to get you started with it. There are a million details that can get you into trouble, you are bound to run into some of them. The much more productive way to get this kind of code going is writing a wrapper in the C++/CLI language. That also lets you wrap a C++ class, something you can't do with P/Invoke. A decent tutorial is available here.
P/Invoke can handle marshaling a managed delegate to a function pointer. So if you expose API's that register a call back function from your DLL and in C# pass a delegate to that function.
There is an example on MSDN of doing this with the EnumWindows function. In that article be careful to pay attention to the line in point 4 that states:
If, however, the callback function can
be invoked after the call returns, the
managed caller must take steps to
ensure that the delegate remains
uncollected until the callback
function finishes. For detailed
information about preventing garbage
collection, see Interop Marshaling
with Platform Invoke.
What that is saying is that you need to make sure that your delegate isn't garbage collected until after the managed code is done calling it by either keeping a reference to it in your code, or pinning it.
See Marshal.GetFunctionPointerForDelegate, which will give you a function pointer for calling managed (i.e. C# code) from unmanaged code.
Have a look at this, Marshal.GetDelegateForFunctionPointer?

Expose Borland C++ methods to C#

I have following method in my Borland C++ code,
static bool UploadBitstream(void)
{
//Some code Implementation
}
And I'm trying to convert it to DLL and access it in C#.
What are the steps I need to follow to Convert the code DLL
and then use it in C# ??
First, you have to make sure that the methods are defined extern. Then you need to declare the method stdcall or pascal calling convention, and mark them dllexport. See code listing below (this is ancient memory for me, so pardon if I am a bit off on modern Borland C++ compilers).
// code.h
extern "C" {
#define FUNCTION __declspec(dllexport)
FUNCTION int __stdcall SomeFunction(int Value);
In the main
#include "code.h"
FUNCTION int __stdcall SomeFunction(int timesThree)
{
return timesThree * 3;
}
Once you've compiled your DLL all you should need to do in .NET to get access to it is use the DLLImport property.
public class stuff
{
[DLLImport("somedll.dll")]
public static extern void UploadBitstream();
}
If you need pointers or anything like that it gets more complicated but for void functions it's that simple.
It should be noted that once you invoke that function the dll will be loaded by your program and won't be released until your program is closed. You can dynamically load dlls but that is much more complicated. I can explain it here if you have a need.
Watch your terminology.
In your example UploadBitstream is function not a method.
If it is indeed a method in a class then it is very difficult to use classes from Borland compiled DLLs.
If your code is actually C not C++ you should be able to create a compatible DLL
for your simple C style functions with C++ Builder.
See the following SO question:
Use a dll from a c++ program. (borland c++ builder and in general)
where I list various compiler settings which will also apply to creating compatible DLLs.

Categories

Resources