Рейтинг:
16
0x01AA
Я делал подобные вещи и раньше, несколько лет назад. Очень прагматичный подход (и, возможно, очень грязный).
Имейте в виду, что я отметил здесь то, что помню...
Часть c#
public class CSharpCom
{
// c++ Callback stuff
private delegate void CPPCallBack([MarshalAs(UnmanagedType.BStr)] string text);
CPPCallBack _CPPCallBack= null;
// To set callback from c++
public void SetCallBacks(IntPtr cppCallBack)
{
_CPPCallBack= (CPPCallBack)Marshal.GetDelegateForFunctionPointer(
cppCallBack,
typeof(CPPCallBack));
}
// Using of the callback
public void LogMsg(string msg)
{
try
{
_CPPCallBack?.Invoke(msg);
}
catch
{
// Error handling
}
}
// You other COM stuff
}
Часть c++ static void __stdcall CPPCallBack(BSTR msg)
{
// Implement callback stuff here
}
int wmain(int argc, char* argv[])
{
CoInitialize(0); // Init COM
BSTR thing_to_send = ::SysAllocString(L"10 20");
BSTR returned_thing;
CSharpDll::_TheClassPtr obj(__uuidof(CSharpDll::TheClass));
// Register the callback
obj->SetCallBacks((INT64)CPPCallBack);
HRESULT hResult = obj->GetTheThing(thing_to_send, &returned_thing);
if (hResult == S_OK) {
std::wcout << returned_thing << std::endl;
return 0;
}
return 1;
}
Я надеюсь, что это поможет
[Редактировать]
код корректируется в соответствии с обратной связью ОП
fisadmaster
Спасибо за код, но часть,
_CPPCallBack = (CPPCallBack) .Маршал.Указатель (
cppCallBack,
typeof (CPPCallBack));
показывает мне ошибку: CSharpCom.CPPCallBack-это тип, который не является допустимым в данном контексте и CSharpCom.CPPCallBack не содержит определения слова "Маршал"
Я включил ваш код в вопрос, чтобы вы могли видеть реализованную сторону C #
Есть идеи?
0x01AA
Хорошо, не уверен, но, возможно, определение делегата должно быть общедоступным. Попробовать это public delegate void CPPCallBack([MarshalAs(UnmanagedType.BStr)] string text);
fisadmaster
Я тоже пробую это сделать, та же проблема
0x01AA
Хорошо, дайте мне "un rato", я попробую настроить небольшой тестовый проект.
0x01AA
Это была просто маленькая опечатка. Я поправил свой ответ.
a.) void SetCallback // void вместо bool (не было проблемы)
b.) _CPPCallBack= (CPPCallBack)Маршал.Указатель(
cppCallBack,
typeof(CPPCallBack));
вместо
_CPPCallBack= (CPPCallBack).Маршал.
fisadmaster
Проверьте изменения, но ничего не происходит, не возвращайтесь к C++
0x01AA
Но он компилируется?
Что говорит вам отладчик с обеих сторон?
Для меня он работает сейчас очень хорошо.
fisadmaster
при отладке форма C # не отображается, форма отображается при освобождении, но функция обратного вызова не выполняется. Мои настройки для 64 бит
0x01AA
Поймите, но я думаю, что это совсем другое дело. В GetThings
вы показываете форму с "ShowForm", которую я не знаю в деталях. Убедитесь, что форма отображается в виде диалога.
fisadmaster
Теперь вы можете увидеть полный код, который я опубликовал для C++ и C#, код кнопки, которая должна отправить сообщение о выпуске::
TheClass myClass = новый TheClass ();
класса MyClass.LogMsg ("Работа !!!");
fisadmaster
Я сделал тест, не показывая форму, и функция работает, обратный вызов отправляет сообщение, но мне нужно отправить несколько сообщений, пока форма отображается
0x01AA
Я думаю, что это хорошая новость. Теперь вы должны показать, как ваш экземпляр Form1 использует обратный вызов.
Кстати: используйте виджет ответа комментария, чтобы ответить. Это делает его более структурированным
fisadmaster
в форме есть кнопка, которая в событии click имеет этот код:
0x01AA
Это как будто никогда не сработает. Имейте в виду, что только BimObjectCSharpClass знает обратный вызов. Либо вы передаете BimObjectCSharpClass в свою форму 1, сохраняете ее в частной переменной, например _BimObjectCSharpClass, а затем вызываете _BimObjectCSharpClass.LogMsg из вашей формы или вы устанавливаете делегат для Form1
fisadmaster
Извините, но я заблудился, BimObjectCSharpClass-это пространство имен, А класс-это класс. на который я ссылался в коде кнопки для доступа к LogMsg, форма имеет то же пространство имен:
0x01AA
Простите, я ошибся.
Я имею в виду, что вам нужно передать класс в вашу форму 1. Имейте в виду, что это не очень хороший способ, но проверить его пока будет нормально. Косметику можно сделать и позже ;)
fisadmaster
Но если я передам класс в форму, то не смогу его увидеть и объявить из C ++?
0x01AA
TheClass
и Form1
оба они находятся на стороне c#. Я не вижу в этом проблемы...
Form1
должен иметь доступ к TheClass.LogMsg
fisadmaster
Извините, я думал, что мне нужно было передать весь код класса в код формы, но я не знаю, как передать класс в качестве ссылки на форму?
0x01AA
Вы доводите меня до предела :). Я точно этого не знаю. Пожалуйста, заранее простите мне все мои ошибки ;)
открытый form1(класса класса )
{
_TheClass= класс;
}
После этого вы можете использовать _TheClass.LogMsg....
Как уже упоминалось, это не самый чистый способ, но очень хорошо подходит для первого испытания
fisadmaster
Я сделал чистую компиляцию, переписал весь код, мне показалось что-то странное и теперь библиотека C # не загружается, если я отключу строку: obj - > SetCallBacks ((long) CPPCallBack); форма отображается, если она включена, она входит в цикл без ответа и заканчивается через несколько секунд. Я считаю, что в этом утверждении есть проблема, есть ли идея проблемы?
fisadmaster
Я делаю простое изменение с long на INT64 и передаю класс в качестве ссылки и теперь работаю, спасибо человеку!!!!.
obj->SetCallBacks((INT64)CPPCallBack);
0x01AA
Спасибо, что согласились и проголосовали.