0

There is already answered question about passing C++ callback into in-process COM method. But the same technique doesn't work for out-of-process usage.

I have a C# interface and it has a method which registers callback/delegate with two parameters.

void ProcessNotification(ConsoleNotificationType type, IntPtr parameter);

This C# interface is registered using Out-of-process COM configuration (exe-file). Now I want to pass a C++ callback function into that method, but Visual Studio gives me an error:

InvalidFunctionPointerInDelegate

So, how can I pass my C++ callback function into the Interface's registering callback function?

1 Answers1

0

There's nothing in COM that will allow you to do this so simply. You really can't even do it in any programmatic paradigm that I can think of. A pointer in one process is meaningless in another process.

The official answer is to define a callback interface and pass a reference to that interface on an implementing object instead of passing a simple function pointer. And, of course, you have to make sure the interface can be proxied. (Alternatively, you can implement IConnectionPointContainer on your server, which is fundamentally the same idea.)

Michael Gunter
  • 12,528
  • 1
  • 24
  • 58
  • I don't understand how is that callback interface from my program will be called at the server program? – Dr. MefistO Nov 04 '20 at 17:10
  • @Dr.MefistO In IDL terminology: Imagine your interface is named `ICallback` and defines a method `HRESULT Invoke()`. You would implement that interface on the client side to do whatever needs to be done in the callback. One the server side, you'll have a method like `HRESULT Request([in] ICallback* pCallback)`. Your server will invoke the callback as `pCallback->Invoke()` (or `pCallback.Invoke()` in C#). Assuming the interface is properly set up for proxying, the `Invoke()` call will be marshaled to the client process. – Michael Gunter Nov 04 '20 at 17:26
  • @Dr.MefistO To clarify: Generally, callback interfaces are defined by the server side of a COM boundary but implemented on the client side. In your case, your server is C#, so the C# side will define the callback interface as something like `public interface ICallback { public void Invoke(); }` and will expose it to COM using the necessary attributes. On the C++ client side, you've likely already got some sort of reference to the types defined in C# (perhaps by using an `#import` directive). So you might just be able to start implementing the interface after defining it (and maybe rebuilding). – Michael Gunter Nov 04 '20 at 17:38
  • Could you tell a little bit more about proxying? How the server's call of the function will be directed into my app? The same COM dll must be loaded (and registered for that before) for both sides? – Dr. MefistO Nov 04 '20 at 17:46
  • Seems, I understand. My client will export the callback interface through Registry, and when the server will want to call a callback it will enumerate connection points, and then will call every Invoke() function, right? – Dr. MefistO Nov 04 '20 at 18:19
  • @Dr.MefistO This is a deep and complex topic -- much too deep for a comments section. More info can be found at https://learn.microsoft.com/en-us/windows/win32/com/inter-object-communication . – Michael Gunter Nov 04 '20 at 18:20
  • @Dr.MefistO See above. Typically, the server defines the callback interfaces and would be required to put it in the registry if necessary (probably necessary in your case). Since your COM server is out-of-process, the server COM dll/exe will not be loaded directly into the memory of the client at runtime. All communications from client to server or vice-versa will be done by proxy & stub objects that exist on the appropriate side. You are already using these features without realizing it. Any out-of-process COM server requires proxyable interfaces to be invoked by a client. – Michael Gunter Nov 04 '20 at 18:24
  • I successfully registered in registry and created an instance of such callback-class in C++, but when I'm passing this class object into Request(callback) it tells me 0x80040155: Interface not registered. What does it mean? – Dr. MefistO Nov 04 '20 at 22:15