Click here to Skip to main content
15,845,742 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have an c dll that I need to call from my c# application.
I have it communicating with the dll, but I am having issues with callbacks.

The c looks like this.

typedef void (CDECLCALL_CONV *ConnectedCB) (DPHandle hdl);

typedef struct
unsigned int size;	// sizeof(DPcbs)
ConnectedCB connectedCB;
.. more callbacks
} DPcbs;

BPS_DP_API unsigned long CDECLCALL_CONV DPSetCallBacks(DPHandle hdl, DPcbs *DPcbs);

What I have tried:

I have created a interface class that wraps the unmanaged code.
It looks like this

  public delegate void ConnectedCB(ref DocProcHandle hdl);

public struct DPcbs
  public uint size;
  public ConnectedCB connectedCB;
... more callbacks
[System.Runtime.InteropServices.DllImportAttribute("DocProc.dll", EntryPoint = "DPSetCallBacks", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
    public static extern uint DPSetCallBacks(ref DocProcHandle hdl, ref DPcbs DPcbs);

Finally My c# calling code
  // this code is in a static class in the constructor
  // it should not be garbage collected right?
  m_events = new DPcbs();
  m_events.connectedCB = connected;
  m_events.size = Convert.ToUInt32(Marshal.SizeOf<DPcbs>());

  wrapper.DPSetCallBacks(ref m_handle, ref m_events);
private void connected(ref DocProcHandle hdl)
  // do something here

The application "stopped working" - no error just a crash.
But it happens AFTER the connected method is called, and before anything else.
If I do not set the connected callback it does not crash. (it seems to crash if it tries to call any of my callbacks)

I have tried everything i can think of to make sure the method does not go through the GC.
The class is static, I have made the method static. I have Alloc'ed both the method and the event.

Is there anything I am missing or doing wrong?
Any suggestions on what to try?
Updated 1-Jun-18 16:26pm

1 solution

You can't pass the delegate to unmanaged code the way you are trying to do. If you are going to pass it as a function pointer inside a structure, you should call:

IntPtr NativeFunctionPointer = Marshal.GetFunctionPointerForDelegate(connected);

Then pass NativeFunctionPointer as the function pointer.

The reason is that a managed delegate consists of more than just a function address. It has code and data like many other .NET classes, so passing its address isn't the same as passing its function entry point.
Share this answer
lewisv 2-Jun-18 11:21am    
That makes sense so here is what I changed it to.

Changed the declaration in the struct to
public struct DPcbs
  public uint size;
  public IntPtr connectedCB;
... more callbacks

The setting the struct i have (i made the items member variables so that the GC would not get rid of them)
      m_c = new ConnectedCB(connected);
      m_p = Marshal.GetFunctionPointerForDelegate(m_c);
      m_events.connectedCB = m_p;

It fires and runs, but the same issue. It blows up directly have the connected delegate finishes.
Richard Andrew x64 2-Jun-18 13:10pm    
I'm confused by your terminology. You say "it fires and runs", then you say "it blows up", "delegate finishes".

Perhaps if you could be specific. Where exactly is the thread when it "blows up?" Is it before, during or after the callback function is executed?

Do you get an error message about the stack being unbalanced?

Have you stepped through the code with the debugger?
lewisv 2-Jun-18 16:19pm    
I am sorry if it was a little confusing. I have run it though the debugger.

private void connected(ref DocProcHandle hdl)
  // this code works fine
  <--- it crashes here after it leaves my callback method and before anything else in the c# application runs

There is no error message, the program just "stops responding" then asks me if I want to debug. No exits the debugger, Yes it will open another visual studio, but then tell me it can't debug.
If I leave the callback out, the application continues with no issues. But of course I need to handle the callbacks.

I am guessing here, but it looks like by setting/calling the callback function I am messing up memory. So the application crashes outside of the c# application and inside the dll that is calling the delegate.
I know the dll works, I have a c application that is calling it and working. To make sure I have not missed anything, I am basically rebuilding the c app in c# and calling the same methods.

Richard Andrew x64 2-Jun-18 16:28pm    
If it crashes after leaving the callback, that is a very strong indicator that the stack is corrupted on the native side. I would recommend making sure that CDECL is the right calling convention for calling into managed code.
lewisv 2-Jun-18 18:01pm    
It has been 10 years since I did any real work in c/c++.
But it looks like cdecl to me.

#define CDECLCALL_CONV __cdecl

typedef void (CDECLCALL_CONV *ConnectedCB) (DPHandle hdl);
BPS_DP_API unsigned long CDECLCALL_CONV getDPDevices(DPHandle devices[], unsigned long* count);

What do you mean by cdecl being right for calling "into" managed code. Is there something else I need to do in my managed c# code?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900