I am attempting to invoke a VBA callback in Excel from C# code using Excel-DNA. After messing around with the particular data types and marshalling declarations, I was able to finally create a working sample:
C# Code
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ProgId("CSharpComObject")]
public partial class CSharpComObject
{
Dictionary<string, Callback> _callbackMap = new Dictionary<string, Callback>();
public void SubscribeStringData(string topic, [MarshalAs(UnmanagedType.FunctionPtr)] Callback callback)
{
_callbackMap[topic] = callback;
}
public void RaiseCallback(string topic, string data)
{
_callbackMap[topic](data);
}
public delegate void Callback([MarshalAs(UnmanagedType.BStr)] string data);
}
VBA Module
Option Explicit
Dim testObj As Object
Sub Subscribe()
Set testObj = CreateObject("CSharpComObject")
testObj.SubscribeStringData "someTopic", AddressOf StringDataCallback
End Sub
Sub StringDataCallback(ByVal data As String)
MsgBox "StringDataCallback Raised [" + data + "]"
End Sub
Question
As you can see from the code sample above, the default COM marshalling for strings is BStr
a.k.a. ByVal ... As String
.
I was wondering if there is a way to pass string data (or any object type for that matter) to the VBA callback ByRef
, and if so, what would the C# declarations and marshalling attributes need to be?
Specifying the parameter as ref string
should work.
See https://msdn.microsoft.com/en-us/library/s9ts558h(v=vs.110).aspx for more information about the string marshaling options.