2016-03-23 31 views
0

我試圖從Excel中使用Excel-DNA從C#代碼調用Excel中的VBA回調。與特定數據類型亂搞和編組聲明之後,我能夠最終建立一個工作示例:Excel DNA - 元帥C#字符串VBA ByRef回調

C#代碼

[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模塊

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 

問題

從上面的代碼示例中可以看出,字符串的默認COM編組爲BStr,也就是ByVal ... As String

我想知道是否有方法將字符串數據(或任何對象類型)傳遞給VBA回調ByRef,如果是的話,C#聲明和編組屬性需要什麼?

+0

你試過'ref string'嗎? – Govert

+0

如果你可以採取早期約束的方法,一個事件會更直接(儘管這不會解決你的問題)。 – Govert

+0

@Govert,我不敢相信它(在嘗試了一堆愚蠢的手動'Marshal'調用之後),但只是把'ref'關鍵字放在C#端就可以了。寫一個正式的答案,我會接受它。 – nicholas

回答

0

指定參數ref string應該有效。

有關字符串封送選項的更多信息,請參閱https://msdn.microsoft.com/en-us/library/s9ts558h(v=vs.110).aspx

+0

...應該工作。 Interop marshaler有時候可能會有驚人的智能。請注意,這相當於手動調用'Marshal.StringToBSTR(..)'並通過'ref'傳遞'IntPtr'。無論哪種方式,性能方面,傳遞字符串'ByVal'或'ByRef'幾乎是相同的,因爲BSTR轉換總是創建一個副本。 – nicholas