Здравствуйте, Odi$$ey, Вы писали:
OE>вопрос — как на С++/CLI подписаться на событие ManagedClass чтоб вызвать функцию callback со строкой msg из параметра события?
Также как и в C# — сделать managed класс с методом который будет подписан на событие и полем в котором будет содержаться адрес каллбека. По факту вызова метода — дергать callback
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
OE>>вопрос — как на С++/CLI подписаться на событие ManagedClass чтоб вызвать функцию callback со строкой msg из параметра события?
TK>Также как и в C# —
не, там бы анонимный делегат прикрутил и все дела
TK>сделать managed класс с методом который будет подписан на событие и полем в котором будет содержаться адрес каллбека.
Здравствуйте, Odi$$ey, Вы писали:
OE>вопрос — как на С++/CLI подписаться на событие ManagedClass чтоб вызвать функцию callback со строкой msg из параметра события?
Например так. Сначала C# класс:
namespace ClassLibrary1
{
public delegate void ResultEventHandler(string msg);
public class ManagedClass
{
public event ResultEventHandler Result;
public void RaiseResult() {
if(Result != null) {
System.Console.WriteLine("Event Raised!");
Result("Aaaaaa!!!");
}//if
}
}
}
Теперь C++/CLI
// TestCpp.cpp : main project file.#include"stdafx.h"using namespace System;
using namespace ClassLibrary1;
typedef void (*Result)(const char* msg);
ref class ResultWrapper
{
public:
ResultWrapper(Result callback) : callback(callback) { }
public:
void Handler(String^ message) {
if(callback) {
Console::WriteLine(L"Handler called!");
callback("Не знаю как сконвертить String^ в const char*\n");
}//if
}
private:
const Result const callback; // С константами тоже могу наврать
};
extern"C"__declspec(dllexport) void Func(Result callback)
{
ManagedClass^ mc = gcnew ManagedClass();
ResultWrapper^ wrapper = gcnew ResultWrapper(callback);
mc->Result += gcnew ResultEventHandler(wrapper, &ResultWrapper::Handler);
mc->RaiseResult();
}
void ResultCallback(const char* msg)
{
Console::WriteLine(L"Callback called!");
}
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Hello World");
Func(ResultCallback);
return 0;
}
ЗЫ. Прошу больно не бить, это был первый опыт
... << RSDN@Home 1.2.0 alpha rev. 675>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Odi$$ey, Вы писали:
>вопрос — как на С++/CLI подписаться на событие ManagedClass чтоб вызвать функцию callback со строкой msg из параметра события?
можно попробовать что-то такое:
C#
namespace CL1
{
public delegate void ResultEvent(string msg);
public class ManagedClass
{
public event ResultEvent OnResult;
public void Run(string message)
{
if (OnResult != null)
{
OnResult(message);
}
}
}
}
C++
using namespace System;
using namespace System::Runtime::InteropServices;
typedef void (*Result)(const char* msg);
void Callback(const char* msg)
{
Console::WriteLine(gcnew String(msg));
}
int main(array<System::String ^> ^args)
{
CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid));
CL1::ManagedClass c1;
c1.OnResult += d;
c1.Run(L"run");
return 0;
}
Здравствуйте, Odi$$ey, Вы писали:
TK>>Также как и в C# — OE>не, там бы анонимный делегат прикрутил и все дела
Ну это тоже самое
TK>>сделать managed класс с методом который будет подписан на событие и полем в котором будет содержаться адрес каллбека. OE>а какой должен быть тип поля?
TK>>сделать managed класс с методом который будет подписан на событие и полем в котором будет содержаться адрес каллбека. OE>а какой должен быть тип поля?
Все равно. Это же С++. Можно сделать IntPtr который потом кастить к нужному типу и через него дернуть каллбек. или сразу поле нужного типа сделать.
Для ценителей можно через Marshal сделать GetDelegateForFunctionPointer (если сигнатуры подходят) и подписать Invoke на событие. В этом случае даже доп. класс не нужен.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, desco, Вы писали:
D> CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid));
работает вроде правильно, правда я не понял, как unicode System.String переданный в делегат из C# компонента правильно преобразовался в не-unicode char* в C++ callback-е
и еще, вот в таком сценарии:
typedef void (CALLBACK *Result)(const char* msg);
extern"C"__declspec(dllexport) void Func(Result result_callback)
{
ManagedClass^ mc = gcnew ManagedClass();
mc->OnResult+= safe_cast<ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(result_callback), ResultEvent::typeid));
mc->Run(); // асинхронная, сразу возвращает управление, ManagedClass генерует событие через некоторое время.
}
никаких заморочек со временем жизни mc и char* msg, которое GetDelegateForFunctionPointer сделает для result_callback не ожидается? (в тестах вроде все работает)
Здравствуйте, Odi$$ey, Вы писали:
D>> CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid));
OE>работает вроде правильно, правда я не понял, как unicode System.String переданный в делегат из C# компонента правильно преобразовался в не-unicode char* в C++ callback-е
+1
OE>и еще, вот в таком сценарии:
OE>typedef void (CALLBACK *Result)(const char* msg);
OE>extern"C"__declspec(dllexport) void Func(Result result_callback)
OE>{
OE> ManagedClass^ mc = gcnew ManagedClass();
mc->>OnResult+= safe_cast<ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(result_callback), ResultEvent::typeid));
mc->>Run(); // асинхронная, сразу возвращает управление, ManagedClass генерует событие через некоторое время.
OE>}
OE>
OE>никаких заморочек со временем жизни mc и char* msg, которое GetDelegateForFunctionPointer сделает для result_callback не ожидается? (в тестах вроде все работает)
Так как ссылка на результат GetDelegateForFunctionPointer хранится в делегате OnResult, то делегат не убьётся и будет жить пока жив ManagedClass^ mc. А в твоём примере он недостижим сразу после выхода из Func.
... << RSDN@Home 1.2.0 alpha rev. 675>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
D>>> CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid));
OE>>работает вроде правильно, правда я не понял, как unicode System.String переданный в делегат из C# компонента правильно преобразовался в не-unicode char* в C++ callback-е
_FR>+1
Хотя, похоже, тут работает тот же механизм, что и при маршалинге строк.
... << RSDN@Home 1.2.0 alpha rev. 675>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Odi$$ey, Вы писали:
D>> CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid));
OE>работает вроде правильно, правда я не понял, как unicode System.String переданный в делегат из C# компонента правильно преобразовался в не-unicode char* в C++ callback-е
Здравствуйте, _Morpheus_, Вы писали:
D>>> CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid)); OE>>работает вроде правильно, правда я не понял, как unicode System.String переданный в делегат из C# компонента правильно преобразовался в не-unicode char* в C++ callback-е _M_>а разве char* получается не юникодный?
Здравствуйте, _FRED_, Вы писали:
_FR>Так как ссылка на результат GetDelegateForFunctionPointer хранится в делегате OnResult, то делегат не убьётся и будет жить пока жив ManagedClass^ mc. А в твоём примере он недостижим сразу после выхода из Func.
в mc->Run(); происходит подписка на SendCompleted локального объекта SmtpClient должен он (mc) дожить до этого события?
Здравствуйте, Odi$$ey, Вы писали:
OE>Здравствуйте, _Morpheus_, Вы писали:
D>>>> CL1::ResultEvent^ d = safe_cast<CL1::ResultEvent^>(Marshal::GetDelegateForFunctionPointer(IntPtr(Callback), CL1::ResultEvent::typeid)); OE>>>работает вроде правильно, правда я не понял, как unicode System.String переданный в делегат из C# компонента правильно преобразовался в не-unicode char* в C++ callback-е _M_>>а разве char* получается не юникодный?
OE>русская строка, байт — буква
байт или char? char может быть двухбайтовым, зависит от режима компиляции...
Здравствуйте, Odi$$ey, Вы писали:
_M_>>байт или char? char может быть двухбайтовым, зависит от режима компиляции...
OE>С++-проект компилируется без unicode, так что одно и тоже
А что, если компилить с юникодом, то
char
будет не однобайтовым
... << RSDN@Home 1.2.0 alpha rev. 675>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.