2016-03-23 10 views
0

Я пытаюсь вызвать обратный вызов VBA в Excel из кода C# с использованием Excel-DNA. После возни с конкретными типами данных и сортировочных декларации, я смог, наконец, создать рабочую пробу:Excel DNA - Marshal C# string для 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 a.k.a. 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 может быть удивительно интеллигентным. Обратите внимание, что это эквивалент ручного вызова 'Marshal.StringToBSTR (..)' и передачи 'IntPtr'' 'ref'. В любом случае, по производительности, передача строки 'ByVal' или' ByRef' почти идентична, так как преобразование BSTR всегда создает копию. – nicholas

 Смежные вопросы

  • Нет связанных вопросов^_^