I have a unmanaged c++ application as COM client and a C# COM server.
now i want COM server can invoke a c++ function.
C# :
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeType
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DeleCallBack(string info);
public DeleCallBack CallBack;
public void SetCallBack(ref IntPtr ptr)
{
CallBack = (DeleCallBack)Marshal.GetDelegateForFunctionPointer(ptr, typeof(DeleCallBack));
}
}
C++:
HRESULT hr = E_FAIL;
CComPtr<WindowsFormsApplicationVC9::_SomeType> spTmp;
hr = spTmp.CoCreateInstance(__uuidof(WindowsFormsApplicationVC9::SomeType));
if (SUCCEEDED(hr))
{
spTmp->SetCallBack(OnCallBack);
}
void OnCallBack(BSTR info)
{
// c++ function call...;
}
I'm not sure it is the right way to just pass the OnCallBack function pointer to SetCallBack.
I noticed that some sample of calling GetDelegateForFunctionPointer should GetProcessAddress to get the function pointer address, but i can't do that since there are may be different c++ COM client with different function name.
any suggestion?
One way to do it is to expose your C++ functions via __declspec(dllexport), then simply write P/Invoke for those functions. Now you can use those P/Invoke functions as delegates.
Deep down this is essentially the GetProcAddress approach but the C# compiler makes it syntactically nicer for you.
Related
I have 2 components:
- .Net Core Application running on Ubuntu OS.
- C++ shared library (.so)
Now I want C++ component to be able to call .Net Core method, either passing interface to C++ component which will use this interface to callback method implementation or passing method as a parameter to C++ component.
High-level example what I am trying to achieve:
C# component :
public interface IDevice
{
void OnDataAvailable(string data);
}
public class Device: IDevice
{
[DllImport("sampleCPPLibrary.so")]
private static extern int SetReceiver(IDevice receiver);
public void OnDataAvailable(string data)
{
Console.WriteLine(data);
}
public void Initialize()
{
SetReceiver(IDevice(this))
}
}
C++ component:
extern "C" {
void SetReceiver(IReceiver * receiver)
{
receiver->OnDataAvailable(10);
}
}
Basically, what I am trying to do is just to pass some kind of "callback" to C++ component and call this "callback" when some event occurs in C++ component.
See See this issue from comments I constructed code where C# calls C and gives it callback delegate. Thus from C then it calls C#, and passes additional int type argument. See comments here from endurox project, and attached c-callback.tar.gz for working example.
I'm working on some code that is not mine, and it passes an argument in c++ to a (managed COM) c# method that doesn't have any parameters. The code works fine, but I don't know why.
Can someone explain what's going on or point me to the c++ constructs that make it possible?
Here's the code:
//---------- C++ ----------
#import "wrapper.tlb" named_guids raw_interfaces_only
BSTR b;
m_wrapper->getException(&b);
CW2A conv(b);
std::string s(conv);
if (! s.empty() ) {
//Perform exception processing
{
//---------- C# Managed COM ----------
public class wrapper : Iwrapper
{
private exceptionStr = String.Empty; // 'exceptionStr' set elsewhere in C# for an eventual pull by C++
public string getException()
{
return exceptionStr;
}
//... other C# methods that may set 'exceptionStr'
}
The COM standard interface does not allow return parametres, since any function returns an HRESULT. So what appear to be as a return value in the COM object in C# is marshalled as a reference in the C++ side.
I currently have a simple unmanaged C++ method which just displays a messageBox. I have created a managed c++ wrapper for this, which I then reference in my c# application.
I need to be able to pass strings and other variables from the c# into the unmanaged c++ and back again but I am having trouble with the conversion of the strings as my c++ knowledge is very basic.
My end goal is to be able to call complicated functions from our legacy unmanaged c++ libraries via my new c# app (not using DLLImport or COM) but I am trying to create a simple example before progressing.
Thanks in advance.
Rich
Assuming the unmanaged C++ method looks something like this:
namespace UnmanagedCpp
{
class MessageBox
{
public:
static void Show(LPCTSTR lpszMessage)
{
::MessageBoxW(NULL, lpszMessage, L"Message", 0);
}
};
}
You could wrap it in something like this:
using namespace System::Runtime::InteropServices;
namespace ManagedCpp
{
public ref class MessageBox
{
public:
static void Show(String^ message)
{
#if defined(UNICODE) || defined(_UNICODE)
IntPtr intPtr = Marshal::StringToHGlobalUni(message);
#else
IntPtr intPtr = Marshal::StringToHGlobalAnsi(message);
#endif
UnmanagedCpp::MessageBox::Show(static_cast<LPTSTR>(intPtr.ToPointer()));
Marshal::FreeHGlobal(intPtr);
}
};
}
If you're planning on doing more extensive interop between C# and C++, I recommend COM as it doesn't require you to write any wrappers (which get really messy in more complicated scenarios), although of course it requires you to modify the existing C++ code.
I'm trying to avoid COM. I'm designing a mixture C# and C++ controls on a C++ exe.
One method I came up with is PInvoking my C++ exe from C#, and sending windows messages to the C# windows. However the amount of methods I call on the controls base class is too long to justify windows messages.
So, if it's possible to export a whole C# interface to a C++ exe, that would be way easier.
I want to avoid COM because I may have to support windows 2000, and doing COM without relying on the manifest would be a deployment hassle on a software package that currently doesn't set much in the registry.
You could write a C wrapper for each of your C++ controls, and PInvoke from C#.
For example this C++ class:
class Example
{
public:
int MyMethod(int param);
}
and in a extern "C" block in your c++ exe:
void * CreateExample() { return new Example(); }
int Example_MyMethod(void * handle, int param) { reinterpret_cast<Example*>(handle)->MyMethod(param)); }
and in C#:
public class Example
{
private IntPtr handle;
public Example()
{
handle = _CreateExample();
}
public int MyMethod(int param)
{
return _MyMethod(param);
}
[DllImport("yourdll.exe")]
private static extern IntPtr _CreateExample();
[DllImport("yourdll.exe")]
private static extern int _MyMethod(IntPtr handle, int param);
}
I use C++/CLI with VS 2010 to do this. You can expose a DLL C interface that can be consumed in the usual way, the implementation would just marshal data from that interface to your C# assembly.
Related question I think Calling C# from C++, Reverse P/Invoke, Mixed Mode DLLs and C++/CLI
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).