C# 从C访问VBA函数#

C# 从C访问VBA函数#,c#,excel,vba,ms-access,office-interop,C#,Excel,Vba,Ms Access,Office Interop,我现在正在处理一些事件。但不幸的是,VBA中的latebinding不支持事件。所以我用的是AddressOf。在Access/Excel(我的应用程序)中,它工作正常() 从C#调用时,文本返回的是“?”而不是正确的文本 谢谢,安迪 public delegate void CallbackMsg(string msg, int unused1, int unused2, int unused3); [ComVisible(true)] public void Tes

我现在正在处理一些事件。但不幸的是,VBA中的latebinding不支持事件。所以我用的是AddressOf。在Access/Excel(我的应用程序)中,它工作正常()

从C#调用时,文本返回的是“?”而不是正确的文本

谢谢,安迪

    public delegate void CallbackMsg(string msg, int unused1, int unused2, int unused3);

    [ComVisible(true)]
    public void TestProcess(int callback)
    {

        CallbackMsg x = (CallbackMsg)Marshal.GetDelegateForFunctionPointer(new IntPtr(callback), typeof(CallbackMsg));
        x.Invoke("Hello Office", 0, 0, 0);

        System.Windows.Forms.MessageBox.Show("Test DOTNET");
    }

VB内部使用的字符串既不是C样式的空终止字符串,也不是“标准”Unicode字符串。它们是一个名为BSTR(基本字符串)的特殊结构

C#有一种通过封送处理类处理它们的方法,因此C#代码如下所示:

public delegate void CallbackMsg(IntPtr bstrMsg, int unused1, int unused2, int unused3);

[ComVisible(true)]
public void TestProcess(int callback)
{
   IntPtr ptrBSTR = Marshal.StringToBSTR("Hello Office");
   CallbackMsg x = (CallbackMsg)Marshal.GetDelegateForFunctionPointer(new IntPtr(callback), typeof(CallbackMsg));
   x.Invoke(ptrBSTR, 2, 4, 6);
   Marshal.FreeBSTR(ptrBSTR); //MUST free it
}
Public Sub CallbackMsg(ByVal s As String, ByVal unused1 As Long, ByVal unused2 As Long, ByVal unused3 As Long)
   Debug.Print "This string came from C#: "; s
   Debug.Print unused1, unused2, unused3
End Sub

Sub TestComVisbl()
   Dim o As Object
   Set o = CreateObject("ComVisbl.Class1")
   Call o.TestProcess(AddressOf CallbackMsg)
End Sub
我用Excel2010进行了测试,但我认为其他VBA产品也是如此。VBA代码如下所示:

public delegate void CallbackMsg(IntPtr bstrMsg, int unused1, int unused2, int unused3);

[ComVisible(true)]
public void TestProcess(int callback)
{
   IntPtr ptrBSTR = Marshal.StringToBSTR("Hello Office");
   CallbackMsg x = (CallbackMsg)Marshal.GetDelegateForFunctionPointer(new IntPtr(callback), typeof(CallbackMsg));
   x.Invoke(ptrBSTR, 2, 4, 6);
   Marshal.FreeBSTR(ptrBSTR); //MUST free it
}
Public Sub CallbackMsg(ByVal s As String, ByVal unused1 As Long, ByVal unused2 As Long, ByVal unused3 As Long)
   Debug.Print "This string came from C#: "; s
   Debug.Print unused1, unused2, unused3
End Sub

Sub TestComVisbl()
   Dim o As Object
   Set o = CreateObject("ComVisbl.Class1")
   Call o.TestProcess(AddressOf CallbackMsg)
End Sub

这是一个猜测,但它可能与unicode有关吗?C#文本将是unicode,但Access(或您使用的函数)可能不是。有趣的是,当我在VBA中移动变量时,工具提示显示“这确实表明您有编码问题。unicode可以是每个字符2个字节。