2016-03-23 9 views
0

Ich versuche, einen VBA-Callback in Excel aus C# -Code mit Excel-DNA aufzurufen. um mit den speziellen Datentypen Nach Messing und Rangier-Erklärungen, konnte ich endlich eine Arbeitsprobe erstellen:Excel DNA - Marshal C# Zeichenfolge zu VBA ByRef in Rückruf

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-Modul

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 

Frage

Wie Sie aus dem Codebeispiel oben sehen können, die Standard-COM-Rangierung für Strings ist BStr auch bekannt als ByVal ... As String.

Ich frage mich, ob es eine Möglichkeit gibt, Zeichenfolgedaten (oder einen beliebigen anderen Objekttyp) an den VBA-Callback weiterzugeben, und wenn ja, wie würden die C# -Deklarationen und Marshalling-Attribute aussehen?

+0

Haben Sie 'ref string' probiert? – Govert

+0

Wenn Sie einen frühbindenden Ansatz wählen können, wäre ein Ereignis einfacher (obwohl das Ihre Frage nicht behandeln würde). – Govert

+0

@ Govert, ich kann es nicht glauben (nach dem Versuch, ein paar doof manuelle 'Marshal'-Aufrufe), aber einfach das' Ref'-Schlüsselwort auf der C# Seite setzen tut es. Schreiben Sie eine formelle Antwort auf, und ich werde es akzeptieren. – nicholas

Antwort

0

Die Angabe des Parameters als ref string sollte funktionieren.

Weitere Informationen zu den String-Marshalling-Optionen finden Sie unter https://msdn.microsoft.com/en-us/library/s9ts558h(v=vs.110).aspx.

+0

... sollte und funktioniert. Der Interop Marshaler kann manchmal überraschend intelligent sein. Beachten Sie, dass dies bedeutet, dass Sie 'Marshal.StringToBSTR (..)' manuell aufrufen und das 'IntPtr' durch' ref' übergeben. In beiden Fällen ist die Übergabe der Zeichenfolge "ByVal" oder "ByRef" in beiden Fällen nahezu identisch, da bei der BSTR-Konvertierung immer eine Kopie erstellt wird. – nicholas