Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Callback функция при вызове С++ DLL из C#  (Прочитано 9639 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ezus
Опытный

il
Offline Offline

« : 13-03-2011 14:52 » 

Очередное непонимание или какая-то глупость.

C# вызывает функцию из неуправляемой С++ DLL передавая туда  Callback функцию.

C#:
Код:
        public delegate bool CallBack ();
        public delegate bool CallBackX(int x);

        [DllImport(_dllName, EntryPoint = "FtaDllDo",   CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
        public static unsafe extern int FtaDllInitModule  ([MarshalAs(UnmanagedType.I4)] int ff, CallBack cbff, ref ZIInitModule st);

        [DllImport(_dllName, EntryPoint = "FtaDllDoX", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
        public static unsafe extern int FtaDllInitModuleX([MarshalAs(UnmanagedType.I4)] int ff, CallBackX cbff, ref ZIInitModule st);

......
            CallBack  myCallBack  = new CallBack (CBfunc);
            CallBackX myCallBackX = new CallBackX(CBfuncX);

            FtaDllInitModule (1, myCallBack,  ref ist); Console.WriteLine("FtaDllInitModule\n");
            FtaDllInitModuleX(1, myCallBackX, ref ist); Console.WriteLine("FtaDllInitModuleX\n");

......

        public static bool CBfunc()
        {
            Console.Write("CBfunc !!!!\n\n");
            return false;
        }

        public static bool CBfuncX(int x)
        {
            Console.Write("CBfuncX x={0}  !!!!\n\n", x);
            return false;
        }




C++ *.h:
Код:
///////////////////////////////////////////////////////////////////////////// 
extern "C"
{
__declspec(dllexport) int FtaDllDo (int ff, bool (*ffcb)(),     void* vptr);
__declspec(dllexport) int FtaDllDoX(int ff, bool (*ffcb)(int x), void* vptr);

}

C++ *.cpp:
Код:
__declspec(dllexport) int FtaDllDo( int ff, bool (*ffcb)(), void* vptr )
{
int rc = 1;

bool rb = (*ffcb)();
return rc;

}

__declspec(dllexport) int FtaDllDoX( int ff, bool (*ffcb)(int x), void* vptr )
{
int rc = 1;

bool rb = (*ffcb)(5);
return rc;
}

Вызов FtaDllDo отрабатывает нормально, а FtaDllDoX - падает при возврате из ffcb.

Сообщает о несогласованности типов.
Наверное это касается int x.
Но я не смог найти примеров или описания - как задать маршалинг на параметры Callback функций. В приводимых примерах нет ничего подходящего.

Может быть ошибка и не здесь, но ГДЕ?

Буду рад любым зацепкам.

Спасибо.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 13-03-2011 18:44 » 

Ну, допустим, такой рабочий пример:

Один проект Server - тип сборки dll для подсистемы Console, native без CLR, платформа x86. Единственный файл main.cpp:
Код: (C++)
#include <iostream>

using namespace std;

extern "C" __declspec(dllexport) int f(int a, bool (__stdcall *b)(), void *c)
{
        cout << "f enter" << endl;
        bool r = b();
        cout << "f leave" << endl;
        return 1;
}

extern "C" __declspec(dllexport) int g(int a, bool (__stdcall *b)(int), void *c)
{
        cout << "g enter" << endl;
        bool r = b(5);
        cout << "g leave" << endl;
        return 1;
}

int __stdcall DllMain(void *hinstDLL, unsigned long dwReason, void *lpvReserved)
{
        return 1;
}

Второй проект Client - тип сборки exe для подсистемы Console, .NET assembly, платформа x86. Единственный файл Program.cs:
Код: (C#)
using System;
using System.Runtime.InteropServices;

namespace Client
{
    class Program
    {
        delegate bool B1();
        delegate bool B2(int x);

        [DllImport("Server.dll")]
        static extern int f(int a, B1 b, IntPtr c);

        [DllImport("Server.dll")]
        static extern int g(int a, B2 b, IntPtr c);

        static bool b1()
        {
            Console.WriteLine("b1 called");
            return true;
        }

        static bool b2(int x)
        {
            Console.WriteLine("b2 called");
            return true;
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Main enter");
            f(1, new B1(Program.b1), IntPtr.Zero);
            g(1, new B2(Program.b2), IntPtr.Zero);
            Console.WriteLine("Main leave");
            Console.ReadKey();
        }
    }
}

Результат работы:
Main enter
f enter
b1 called
f leave
g enter
b2 called
g leave
Main leave

Среда Visual Studio 2008, Windows 7.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
ezus
Опытный

il
Offline Offline

« Ответ #2 : 14-03-2011 06:46 » 

Dimka Спасибо, Вроде заработало


Добавлено через 51 минуту и 41 секунду:
Как и ожидалось - только кажется.

Чем можно объяснить такой феномен:
старт из-под С++ 6.0 и напрямую *.exe работает нормально, а старт из-под VS-2010(C#) падает, причем не всегда?
« Последнее редактирование: 14-03-2011 07:45 от ezus » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 14-03-2011 13:48 » 

ezus, такой феномен можно объяснить глюками, которые к механизму callback между managed и unmanaged кодом отношения не имеют.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
ezus
Опытный

il
Offline Offline

« Ответ #4 : 15-03-2011 11:13 » new

Спасибо, я уже понял, что тут связи нет.
А глюки - это глюки и черт его знает, как с ними бороться
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines