Функции асинхронного обратного вызова
Перспектива: я обновляю несколько приложений VB6 ActiveX до C # .net, которые все общаются друг с другом с помощью функций обратного вызова, которые они регистрируют с помощью исполняемого файла VC ++. Net.
Я не могу воспроизвести следующие функции VB6 в C #:
Способность VB6 передавать VC ++, экземплярный класс, содержащий метод, в качестве параметра функции обратного вызова, который VC ++ затем регистрирует в качестве функции обратного вызова для асинхронного взаимодействия.
Обновление прошло очень хорошо, кроме одной этой проблемы: Функции CallBack
... и я застрял на нем уже две недели. Пожалуйста, помогите мне !!!
Я выяснил, как передать функцию обратного вызова в качестве делегата, что мне удалось получить с помощью C # DynamicInvoke, однако мне действительно нужно это для работы в VC ++.
Сообщение об ошибке Я получаю от оператора VC ++ invoke
«Неверное количество параметров» .
НИЖЕ, я обрисовал в общих чертах функциональность VB6 и VC ++, которая обрабатывает асинхронные обратные вызовы. Каждый компонент ActiveX VB6 передает класс, содержащий один метод, в качестве функции обратного вызова в исполняемый файл VC ++, который сохраняет обратные вызовы в массиве для последующего использования. Поскольку это существующий код, он работает как ожидалось.
Ниже приводится экземпляр VB6 класса Class1
, используемый в качестве обратного вызова:
Обратите внимание: Attribute Notify.VB_UserMemId = 0
VERSION 1.0 CLASS
BEGIN
MultiUse = -1
Persistable = 0
DataBindingBehavior = 0
DataSourceBehavior = 0
MTSTransactionMode = 0
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Sub Notify(ByVal message As Integer, ByVal data As Variant)
Attribute Notify.VB_UserMemId = 0
MsgBox Str$(message) + " " + data, vbInformation, Form1.Text2
End Sub
Приведенный выше код был упрощен во избежание путаницы.
Ниже приведен код VB6 , который создает исполняемый файл VC ++ (VCCallbackHandler
) и передает ему экземпляр Class1
в качестве параметра обратного вызова
Dim VCCallbackHandler New VCCallbackHandler.VCCallbackHandler
Dim c1 As New Class1
Private Sub Register_Click()
Dim i as int
i = VCCallbackHandler.Register(c1, "NameOfApplication")
End Sub
Код VC ++ регистрирует обратные вызовы (см. Ниже), а затем (асинхронно) VC ++ может использовать обратные вызовы, если это вызвано каким-либо другим событием (см. Ниже «BroadCast»). В этом случае VC ++ exe выступает в качестве центрального обработчика обратного вызова для нескольких одновременно работающих приложений. Каждое приложение зарегистрировало свой обратный вызов с помощью обработчика обратного вызова VC ++, и когда одно приложение запрашивает обратный вызов VC ++, вызывая другое событие, все обратные вызовы вызываются. Таким образом, обработчик обратного вызова позволяет всем этим другим приложениям связываться друг с другом.
Ниже приведен соответствующий код обратного вызова VC ++. Net .
Регистрация обратных вызовов:
#define MAXREG 20
typedef struct tagRegElement {
char name[20]; // Name of registered application
_Callback *p_Callback; // Callback wrapper class
} REG_ELEMENT;
public:
REG_ELEMENT Registry[MAXREG];
short CBreqDlgAutoProxy::Register(LPDISPATCH callback, LPCTSTR name)
{
for (int i = 0;i<MAXREG;i++){
if(!(theApp.Registry[i].name[0]))
{
RegIndex = i;
strcpy(theApp.Registry[i].name,name);
theApp.Registry[i].p_Callback = new _Callback(callback);
return i;
}
}
return -1;
}
Вызов обратных вызовов:
BOOL CBreqDlgAutoProxy::Broadcast(short message, const VARIANT FAR& data)
{
for (int i = 0;i<MAXREG;i++){
if(theApp.Registry[i].name[0] && (i != RegIndex)){
if (!theApp.Registry[i].p_Callback->Notify(message,data,theApp.Registry[i].name))
DeRegister(i);
}
}
return TRUE;
}
BOOL _Callback::Notify(short message, VARIANT data, char* RegisteredName)
{
static BYTE parms[] = VTS_I2 VTS_VARIANT;
InvokeHelper(0x0, DISPATCH_METHOD, VT_EMPTY, NULL, parms, message, &data);
return TRUE;
}
Примечание. ВЫШЕ РАБОТАЕТ.
Существует два возможных решения:
- C #: как заставить C # передать метод в качестве параметра. Я понял, как это сделать с помощью делегата, но VC ++ хочет, чтобы метод не был делегатом.
- VC ++: Как заставить VC ++ обрабатывать делегат вместо метода в качестве обратного вызова для вызова.
У меня не было успеха ни с одним из следующих c # фрагментов кода: `
Marshal.GetFunctionPointerForDelegate
GCHandle
KeepAlive
Я надеюсь, что кто-то там имел эту проблему, и может пойти ... SNAP ... это легко ... использовать это ... Скрещенные пальцы.