Форум Beholder
http://beholder.ru/bb/

Работа с BeholdRC.dll в .NET (C#)
http://beholder.ru/bb/viewtopic.php?f=10&t=9624
Страница 1 из 2

Автор:  BARBOSS [ 18 июл 2010, 14:29 ]
Заголовок сообщения:  Работа с BeholdRC.dll в .NET (C#)

Всем привет!
Вот появилось желание написать небольшое приложение, которое бы реагировало на нажатие кнопок на пульте. Думал изначально написать программку для управления PC (но не стал изобретать велосипед, т.к. уже существует достаточное множество таких приложений). Сам использую "ПерехватЪ".

Вообщем вопрос:

Пробовал ли кто обернуть BeholdRC.dll на C# и работать с ее функционалом?

Слил "API, позволяющий организовать поддержку пульта ДУ Behold TV в собственных приложениях." но так и не понял как собрать это все в dll. Там 2 файла (с++): BeholdRC.cpp и BeholdRC.h. Что с ними делать, как получить из них сборку которую бы увидел .NET?

Может у кого есть исходники C++ приложения, то что в сдк?!

Автор:  hd44780 [ 19 июл 2010, 09:42 ]
Заголовок сообщения:  Re: Работа с BeholdRC.dll в .NET (C#)

писал(а):
Слил "API, позволяющий организовать поддержку пульта ДУ Behold TV в собственных приложениях." но так и не понял как собрать это все в dll. Там 2 файла (с++): BeholdRC.cpp и BeholdRC.h. Что с ними делать, как получить из них сборку которую бы увидел .NET?

Те исходники для C# не годятся. Их можно использовать только в программах на C++.
В шарпе необходимо подключать BeholdRC.dll через DllImport.

Могу конкретным кодом помочь, если надо.

Автор:  BARBOSS [ 19 июл 2010, 17:18 ]
Заголовок сообщения:  Re: Работа с BeholdRC.dll в .NET (C#)

Спасибо, если не трудно покажите как вытянуть функции с BholdRC.dll.

Вот приведу свое решение написанное(переписанное) на C#:

Для начала объявил класс:
Код:
public class BeholdRC
   {
      public static IntPtr hLib = Imports.LoadLibrary("BeholdRC.dll");
      public static IntPtr GetCardCount = Imports.GetProcAddress(hLib, "GetCardCount");
      public static IntPtr OpenCard = Imports.GetProcAddress(hLib, "OpenCard");
      public static IntPtr GetRemoteCode = Imports.GetProcAddress(hLib, "GetRemoteCode");
      public static IntPtr GetRemoteCodeEx = Imports.GetProcAddress(hLib, "GetRemoteCodeEx");
      public static IntPtr UnInit = Imports.GetProcAddress(hLib, "UnInit");

      public static bool init;

      public BeholdRC()
      {
         init = false;

         if(GetCardCount == null || OpenCard == null || GetRemoteCode == null || UnInit == null) // GetRemoteCodeEx may be absent in library. Don't check for it.
         {
            Imports.FreeLibrary(hLib);
         }
      }
      public void Dispose()
      {
            Imports.FreeLibrary(hLib);
      }
   }


Потом объявим делегаты:
Код:
#region Delegates

   //  Объявляем делегаты, к которым будет приводиться нужная неуправляемая функция
   public delegate int GetCardCountInvoker();
   public delegate bool OpenCardInvoker();
   public delegate int GetRCCodeInvoker();
   public delegate ulong GetRCCodeExInvoker();

#endregion


Потом объявим класс импорта:
Код:
#region Import
   
   /// <summary>
   /// Импорт необходимых функций Windows API
   /// Смотрите также документацию по атрибуту DllImportAttribute
   /// http://msdn.microsoft.com/library/rus/default.asp?url=/library/rus/cpref/html/frlrfsystemruntimeinteropservicesdllimportattributememberstopic.asp
   /// </summary>
   public class Imports
   {
      [DllImport("kernel32.dll")]
      public static extern IntPtr LoadLibrary(string lpFileName);

      [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
      public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

      [DllImport("kernel32.dll", SetLastError = true)]
      public static extern bool FreeLibrary(IntPtr hModule);
   }

   #endregion


И вот приведу пример метода:

Код:
#region Implemented Methods
      
      public static int BTV_SelectCard()
      {
         return BTV_SelectCard(0);
      }

      public static int BTV_SelectCard(int idx)
      {
         int i;
         int cnt;

         GetCardCountInvoker cardCountInvoker = Marshal.GetDelegateForFunctionPointer(BeholdRC.GetCardCount, typeof(GetCardCountInvoker)) as GetCardCountInvoker;
         OpenCardInvoker opencardInvoker =  Marshal.GetDelegateForFunctionPointer(BeholdRC.OpenCard, typeof(OpenCardInvoker)) as OpenCardInvoker;
      
         if(idx >= 0 && BeholdRC.hLib != null)
         {
            cnt = cardCountInvoker();

            if(cnt > idx)
            {
               for(i = 0; i < cnt; ++i)
               {
                  if(opencardInvoker())
                  {
                     if(idx == 0)
                     {
                        BeholdRC.init = true;
                        return 1;
                     }
                     --idx;
                  }
               }
            }
         }

         BeholdRC.init = false;

         return 0;
      }
#endregion


Вот тут -
Код:
opencardInvoker()
работает не так как надо. Проблема в том если объявить делегат
Код:
public delegate bool OpenCardInvoker(ulong index);
потому как в C++ SDK функия определяется
Код:
typedef BOOL  (__cdecl OPENCARD) (IN ULONG ulCardIdx);
с входным параметром
Код:
IN ULONG ulCardIdx
, то падает приложение с эксепшеном
Код:
A call to PInvoke function 'IRControlTool!IRControlTool.OpenCardInvoker::Invoke' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
- Типа не совпадают параметры нашего делегата и функции из BeholdRC.dll.

Автор:  hd44780 [ 19 июл 2010, 19:50 ]
Заголовок сообщения: 

Слишком сложно.
Можно проще. Завтра в течении дня кину.

Автор:  BARBOSS [ 19 июл 2010, 20:41 ]
Заголовок сообщения: 

Спасибо заранее.

Автор:  hd44780 [ 20 июл 2010, 09:50 ]
Заголовок сообщения: 

Лови - http://hd44780.narod.ru/BeholdRcTest.zip

100% C#. VS.NET 2005.
Без подключения WinAPI.

Там 2 проекта - .NET обертка - Dll и демонстрационне приложение, аналогичное тому, которое дают бехолдеровцы.
Я там особо красоту не наводил, показал лишь идею. Оберточную dll делать необязательно, там достаточно одного класса-враппера.

В BeholdRc.dll есть еще ряд интересных функций - получить имя тюнера, его системный идентификатор и пр. Но разработчики не дали их спецификаций, увы ..

Если что - обращайся.

Автор:  BARBOSS [ 20 июл 2010, 10:04 ]
Заголовок сообщения: 

Спасибо, посмотрю. А по поводу функий - я вчера Olly Deb. дебажил BeholdRC.Dll видел их, но не стал заморачиваться=).

И еще, если можешь, выложи пжта BeholdRC.Dll, я просто на работе, и забыл слить дома...

Автор:  hd44780 [ 20 июл 2010, 12:02 ]
Заголовок сообщения: 

писал(а):
И еще, если можешь, выложи пжта BeholdRC.Dll, я просто на работе, и забыл слить дома...

Бери - http://hd44780.narod.ru/BeholdRCdll.zip
Dll-ка от последнего софта, v5.10.

Если разберешься с теми функциями, стукни в личку, плиз.
Хотя если они недокументированы, пользоваться ими опасно - версию новую сделают - поменяют чего-нибудь, глюки начнутся.

PS
Я на работу занес архив инсталлированного ПО. Работать, конечно, не работает, но можно брать оттуда что надо.

Автор:  BARBOSS [ 20 июл 2010, 12:29 ]
Заголовок сообщения: 

Спасибо за длл-ку. Ок, как че найду отпишусь.

Вот кста те функции:
Изображение
Все у которых в столбце Section значение .text

Автор:  hd44780 [ 20 июл 2010, 15:21 ]
Заголовок сообщения: 

Все равно эт тебе не .NET dll, какие там аргументы и возвращаемые значения остается только гадать. Или лезть в нее какой-нибудь трассировкой.

Имя тюнера я наловчился иначе получать :lol: .

Автор:  BARBOSS [ 21 июл 2010, 01:15 ]
Заголовок сообщения: 

Твоим способом:
Код твоего приложения:
Код:
textBoxLog.Text = String.Concat(BeholdRcWrapper.BeholdRcWrapper.GetDeviceNameA(0), "\r\n");

Вот код в классе врапере:
Код:
[DllImport("BeholdRC.dll", SetLastError = true)]
public static extern string GetDeviceNameA(int card);


Но 1 но во время дебага, твоего апликейшена выкидывает PInvokeStackImbalance:

Код:
PInvokeStackImbalance was detected
Message: A call to PInvoke function 'BeholdRcWrapper!BeholdRcWrapper.BeholdRcWrapper::OpenCard' has unbalanced the stack.
This is likely because the managed PInvoke signature does not match the unmanaged target signature.
Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.


Но результат есть:
Изображение

Автор:  BARBOSS [ 21 июл 2010, 02:37 ]
Заголовок сообщения: 

Разрулил!!!!
Вот как надо определять импорт:
Код:
[DllImport("BeholdRC.dll", CallingConvention=CallingConvention.Cdecl, SetLastError = true)]

Автор:  BARBOSS [ 21 июл 2010, 02:39 ]
Заголовок сообщения: 

читаем http://msdn.microsoft.com/en-us/library ... tion(VS.71).aspx

Автор:  hd44780 [ 21 июл 2010, 09:37 ]
Заголовок сообщения: 

BARBOSS, спасибо за исследования.
Дома проверю у себя на моих двух компах.
Воспользуюсь когда нужно будет.

Автор:  terier [ 10 дек 2010, 20:56 ]
Заголовок сообщения: 

См. http://beholdtv.codeplex.com

Страница 1 из 2 Часовой пояс: UTC + 3 часа