this is my code
public delegate void NotifyFunc(enumType notificationType, IntPtr data);
[DllImport("VssSdkd")]
public static extern void startVssSdkClientEcho(string IpAddress,
long port, NotifyFunc notifyFunc, eProtocolType proType, bool Req);
am call the function like
CallBack calbck = new CallBack(TestDllImport.Callbackas);
startVssSdkClientEcho("192.168.10.240", 12050, calbck, TestDllImport.eProtocolType.eProtocolType_VssSdk, false);
here my receving callback function is
static public void Callbackas(eNotificationType type, IntPtr datas) {}
here first time am receving data and then it's giving Error msg like :
run time check failure #0 - the value if ESP was not properly saved across a function call.
this is usually a result of calling a function declared with one calling convention
with a function pointer declared with a different calling convention
please help me to identify my error... thanks in advance
Is this your code you are calling (sorry cursory search could only find your other post referring to startVssSdkClientEcho). Is it decalred cdecl (i.e. it has no __declspec at all) or is it stdcall. If it is cdecl you need to add CallingConvention attribute to the DllImport
i.e.
[DllImport("VssSdkd", CallingConvention=CallingConvention.Cdecl)]
Of course it might also be the callback calling convention at fault which is another issue.
Related
Suppose we have the following C++ code:
typedef int (*getIntPtr)(void);
extern "C" __declspec(dllexport) void InvokeFuncPtr(getIntPtr funcPtr) {
std::wcout << funcPtr();
}
We can match this definition in C#:
[DllImport("NativeLib.dll", CallingConvention = CallingConvention.Cdecl), SuppressGCTransition]
public static unsafe extern void InvokeFuncPtr(delegate* unmanaged[Cdecl]<int> funcPtr);
And then we can use this function like so:
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
public static int ReturnInt() => 123;
// ... Elsewhere:
unsafe {
InvokeFuncPtr(&ReturnInt);
}
When InvokeFuncPtr is marked with SuppressGCTransition this results in the program crashing with the error "Fatal error. Invalid Program: attempted to call a UnmanagedCallersOnly method from managed code.". If we remove the SuppressGCTransition attribute it works as expected, and 123 is printed to the console.
Is this expected behaviour? I imagine it amounts to the runtime seeing ReturnInt() as being invoked from managed code, simply with a couple of extra steps of indirection. If so, is there any way around this, or should I simply leave the SuppressGCTransition attribute off?
Yes, you should leave off SuppressGCTransition, as the stack is what the runtime uses to identify whether the caller is managed or unmanaged.
If there is no transition in the stack, there is no way for the runtime to tell that the stack transitioned to unmanaged.
Alternatively, you can leave off UnmanagedCallersOnly, and instead marshal the delegate with Marshal.GetFunctionPointerForDelegate.
I got an external DLL (c++) with the follwing method:
void _stdcall Set_Config(char* config)
I use the following c# code to call the method:
[DllImport(DllName,CharSet=CharSet.Auto)]
public static extern void Set_Config(String config);
But when i execute my c# code i get either an acces violation exception or an System.Runtime.InteropServices.SEHException.
(My dll is 32 bit, and my c# compiler compiles to 32 bit)
I also tried to replace String config with Stringbuilder, but the same result.
Can someone help me with this problem or give some example code how i have to call the c++ method?
CharSet.Auto will encode as UTF-16. But your function accepts char* and so the text is encoded as 8 bit text, presumably ANSI.
[DllImport(DllName, CharSet = CharSet.Ansi)]
public static extern void Set_Config(string config);
Calling the function is trivial.
I am assuming that the string is being passed into the function. On the other hand, it is odd that the parameter is char* rather than const char*. Either the developer doesn't know how to use const, or perhaps the function really does send data back to the caller.
If the data flows the other way, then you are in trouble. You'd need to pass a StringBuilder but you've no way to tell the DLL how large a buffer is available. If the data is flowing the other way then the code looks like this:
[DllImport(DllName, CharSet = CharSet.Ansi)]
public static extern void Set_Config(StringBuilder config);
Call the function like this:
StringBuilder config = new StringBuilder(256); // cross your fingers
Set_Config(config);
Either way, you need to be more clear as to what this function is actually doing. You cannot hope to call this function until you know whether to pass data in, or receive data out.
You have to pass an IntPtr which is a raw pointer to your string. (From my memories, Marshal.StringToBSTR)
public static extern void Set_Config(IntPtr config);
I'm having real troubles trying to use a c++ callback in C# and any help from you would be really appreciated.
The first thing that the code do is to create an event:
uEvent = CreateEvent(NULL, true, false, "EventName");
After that, I've got that c++ function that implements a callback in c++:
int RegisterCallback(TCallbackType CallbackType, void *pLLTProfileCallback, void *pUserData)
The CallbackType is used to specify a stdcall. Then, the pLLTProfileCallback would be the name of the function to call, and finally, the user data.
With that function, I'm able to make a callback to another function by typing the following:
RegisterCallback(STD_CALL, (void*)FunctionName, 0)
Where the other function is:
void __stdcall FunctionName(const unsigned char* pucData, unsigned int uiSize, void* pUserData)
And then, I've got the code to wait for the event:
WaitForSingleObject(uEvent, 1000)
My problem comes when I try to do that in C#. The first thing I do is import the RegisterCallback Function from the dll:
[DllImport(DRIVER_DLL_NAME, EntryPoint = "s_RegisterCallback",CallingConvention = CallingConvention.StdCall)]
internal static extern int RegisterCallback(uint pLLT, TCallbackType CallbackType, IntPtr pLLTProfileCallback, IntPtr pUserData);
But then, I don't know how to proceed. Could you please help me?
Delegates in C# which is equivalent to C++ callback.
Please refer to MSDN Introduction & Syntax and usage for same
Here is my C++ Code:
This function is exported in my DLL.
EXPORT set_hook(fnc_public_hook hook){
public_hook = hook;
}
Now if I hook it from unmanaged code like following everything works fine.
set_hook(my_fnc);
Now before every event in my DLL my_fnc is called, so I can do some pre process on data.
The problem is that I don't know how to do this in .NET.
How to get .NET function pointer ? And how to use set_hook() to call my .NET function before every event ?
using System.Runtime.InteropServices;
Somewhere, create a delegate to your function you would like called
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint YourFunctionDelegate();
Set your delegate to point to your function, ie in your constructor,
YourFunctionDelegate = myDotNetFunc;
In NativeMethods class inside your namespace,
[DllImport("YourDLL.dll", EntryPoint = "set_hook", CallingConvention = CallingConvention.Cdecl)]
private static extern int setHook([MarshalAs(UnmanagedType.FunctionPtr)]YourFunctionDelegate myDelegate);
Finally, you can call your c++ function with
NativeMethods.setHook(YourFunctionDelegate);
Make sure you know which calling convention is appropriate.
EDIT: Dont get garbage collected!
http://msdn.microsoft.com/en-us/library/ms182294%28v=vs.80%29.aspx
Preventing unmanaged function pointer garbage collection
I am calling an function from a DLL which is loaded run-time (Using LoadLibrary()).
This DLL is written in C++ and my code is in C#.
API requires Structure Pointer. I am passing "ref" instead of Pointer.
While doing this, I getting "AccessViolationException". After 3 days of Googling, I think the problem could be solved by Pinning the Structure so that GC won't disturb it.
(See: Passing struct by reference causing AccessViolationException)
My question is Can I pin a structure without using any Pointers? Because I don't want to pass a pointer to function.
Code is as follows:
public class TestClass
{
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
public struct MsgFormat
{
public Int32 MsgID;
public Int32 RxID;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=13)]
public Char[] MsgData;
}
unsafe public delegate Int32 ReadMessage(Int32 ConnectID,ref MsgFormat Message);
ReadMessage fp_ReadMessage;
void Connection()
{
IntPtr pDLLHandle;
pDLLHandle=LoadLibrary(Connect.dll); // Load Required DLL
IntPtr fPtr= GetProcAddress(pDLLHandle,"ReadMessage");
fp_ReadMessage=(ReadMessage)Marshal.GetDelegateForFunctionPointer(fPtr,typeof(ReadMessage)); // Get Function Pointer for API
}
void Read()
{
MsgFormat Rx_Msg=new MsgFormat();
Int32 nReturnValue;
Int32 nConnectID=0; // Value is assigned for Testing the Function
/* Also Tried:
Rx_Msg.MsgData=new Char[13]; */
nReturnValue= fp_ReadMessage(nConnectID,ref Rx_Msg); // "ReadMessage" will return info in Rx_Msg;
/* Call to fp_ReadMessage gives me "AccessViolationException". I have tried making that Ref to IntPtr even Passed IntPtr.Zero Still I am getting the error */
}
}
}
Regards,
Swanand!
I don't think pinning will help you here. The CLR will ensure that any parameters you pass to an interop call don't move in memory until the call returns.
So the only situation when you need to do some manual pinning is if the function you call stores the pointer and writes to it later.
To know why you get an access violation, we need more information about the native function you're calling (like the function signature).