Маршалинг структуры обратного вызова с на C#

#c# #c #dll #marshalling

#c# #c #dll #Сортировка

Вопрос:

у меня возникли некоторые проблемы в моем проекте.

Я использую c .скомпилированная dll (у меня нет возможности изменить ее, перекомпилировать или изменить) у меня есть файл .h, где есть некоторая (плохо документированная) информация. Эта библиотека dll используется для взаимодействия с устройством, подключенным через USB. Устройство правильно сконфигурировано, и с помощью функции, предоставляемой dll, у меня есть абсолютная уверенность в том, что оно правильно отвечает на вызов dll. Сортировка с c и c # довольно проста, пока мне не придется использовать обратный вызов для регистрации на какое-либо событие, генерируемое устройством.

Это важная часть c .h, которую я должен использовать в c # (первое и второе события являются поддельными именами)

 //First Event data
typedef struct tagFIRST_EVENT {
    int a; 
    int b; 
    int c;
} FIRST_EVENT;

//SecondEvent data
typedef struct tagSECOND_EVENT {
    int e; 
    int f; 
} SECOND_EVENT;

//first event callback?
typedef void (CALLBACK *FIRTS_EVENT_LISTENER)(FIRST_EVENT *event, void *userData);  

//second event callback?
typedef void (CALLBACK *SECOND_EVENT_LISTENER)(SECOND_EVENT *event, void *userData);


//Register to all given callback in the struct LISTENER
int WINAPI RegisterEvents(LISTENER *listenerGroup );

typedef struct tagLISTENER {
    FIRTS_EVENT_LISTENER first_listener;
    SECOND_EVENT_LISTENER second_listener;
    void * userData;
} LISTENER;
 

У меня возникли некоторые проблемы с сортировкой, чтобы иметь c .dll вызывает мои функции c #, которые я определил для обработки события, генерируемого устройством.

Я следовал многим найденным примерам, но у меня не было возможности использовать эти функции надлежащим образом. В основном сбой приложения c # без какой-либо дополнительной информации (я думаю, потому что ошибка находится в c dll, и я не могу поймать ошибку).

Могу ли я привести пример реализации, учитывая приведенный выше фрагмент кода?

Я глубоко искал и нашел только похожий вопрос, но ни один из них не смог мне помочь. Я здесь для любых разъяснений, спасибо за совет!

Комментарии:

1. Вы не упомянули, какие у вас проблемы…

2. Я прервал эту вечеринку, извините. Я отредактирую сообщение, чтобы ответить на ваш вопрос.

3. Сохраняете ли вы экземпляр делегата обработчика до тех пор, пока больше обратных вызовов не ожидается?

4. Как это можно сделать? Я видел какой-то пример на c , но подумал, что это не главное (возможно, я подумал, что это плохо), могу ли я привести небольшой пример?

Ответ №1:

Ну, я не знаю, сколько маршалинга вы выполнили, поэтому я предполагаю, что вы создали бинарно-совместимые типы в C # для FirstEvent и SecondEvent типы данных.

Для указателей на функции все, что вам нужно, это IntPtr .

После всего этого (что я расширю, если вы не создали типы, совместимые с двоичными файлами), все, что вам нужно сделать, это создать делегат, который сам по себе совместим с двоичными файлами:

 delegate void FirstEventListener(ref FirstEvent firstEvent, IntPtr userData);
delegate void SecondEventListener(ref SecondEvent secondEvent, IntPtr userData);
 

затем вы можете создать экземпляр делегата для фактического обработчика и использовать [Marshal.GetFunctionPointerForDelegate](http://msdn.microsoft.com/en-us/library/at4fb09f.ASPX) для получения указателя (как IntPtr ),

Не забывайте поддерживать этот экземпляр делегата в рабочем состоянии (т.Е. Хранить ссылку на него) до тех пор, пока может быть вызван обратный вызов.

Комментарии:

1. Большое спасибо, я протестирую и посмотрю!! Я опубликую некоторые варианты моего решения на c #, если я не смогу это исправить.

2. Решаемая большое спасибо, я делал одну СЕРЬЕЗНУЮ ошибку. Две структуры (FirstEvent и SecondEvent) не были основаны на ref. Еще раз спасибо!