Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > из C++ в C#


Автор: qpeHukc 27.1.2006, 02:09
есть код на C++, достающий функции из dll - ки. Суть функций - работа с платой АЦП. Нужно переписать этот код на C#

Код

#define IFC(type) virtual type __stdcall
#define FDF(type) type __stdcall

#ifndef __LUNKNOWN__
#define __LUNKNOWN__
struct LUnknown
{
   IFC(HRESULT)   QueryInterface(const IID& iid, void** ppv) = 0;
   IFC(ULONG)     AddRef() = 0;
   IFC(ULONG)     Release() = 0;
};
#endif

struct IDaqLDevice:LUnknown
{
   IFC(ULONG)  inbyte ( ULONG offset, PUCHAR data, ULONG len=1, ULONG key=0) = 0;
   IFC(ULONG)  inword ( ULONG offset, PUSHORT data, ULONG len=2, ULONG key=0) = 0;
   IFC(HANDLE) OpenLDevice() = 0;

... и так далее

};

DEFINE_GUID(IID_ILDEV, 0x32bb8320, 0xb41b,0x11cf, 0xa6, 0xbb, 0x00, 0x80, 0xc7, 0xb2, 0xd6, 0x82);


не могу найти соотв. конструкций и типов

Автор: mr.DUDA 27.1.2006, 09:19
Цитата(qpeHukc @ 27.1.2006, 01:09 Найти цитируемый пост)
не могу найти соотв. конструкций и типов

их и не будет.

В дотнете работать с COM на порядок проще:
1) создаём например Console Application
2) заходим в "Add Reference..."
3) переходим на закладку COM, находим там нашу dll'ку (или если там нету, то идём в "Browse" и находим её там)
4) жмём OK - в проект добавляется набор классов-wrapper'ов для нашей dll, работаем с ними как с обычными классами

Если нужна помощь - скидывай в аттаче свою длл-ку в зипе, я напишу пример приложения.

Автор: Cr@$h 27.1.2006, 11:40
Т.е. классы импорта создаются автоматически? Как тогда визард узнает, какие правила по вызовам использовались в dll?

Автор: mr.DUDA 27.1.2006, 13:05
Цитата(Cr@$h @ 27.1.2006, 10:40 Найти цитируемый пост)
Т.е. классы импорта создаются автоматически? Как тогда визард узнает, какие правила по вызовам использовались в dll?

Да, автоматически. Как узнает - это дело визарда smile

Автор: qpeHukc 27.1.2006, 20:58
Цитата(mr.DUDA @ 27.1.2006, 09:19)
Цитата(qpeHukc @  27.1.2006,  01:09 Найти цитируемый пост)
не могу найти соотв. конструкций и типов

их и не будет.

В дотнете работать с COM на порядок проще:
1) создаём например Console Application
2) заходим в "Add Reference..."
3) переходим на закладку COM, находим там нашу dll'ку (или если там нету, то идём в "Browse" и находим её там)
4) жмём OK - в проект добавляется набор классов-wrapper'ов для нашей dll, работаем с ними как с обычными классами

Если нужна помощь - скидывай в аттаче свою длл-ку в зипе, я напишу пример приложения.

к сожалению в dll - ке не COM.

Выводится сообщение : A reference to '...путь\lcomp.dll' could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component.

Автор: qpeHukc 27.1.2006, 21:17
Может это поможет лучше понять, что происходит в dll-ке. Вот как происходит работа с функциями длл-ки :

Код

int main()
{

ADC_PAR ap;
PLATA_DESCR pd;
SLOT_PAR sl;

   ULONG slot = 0;

   trace("Get IUnknown pointer");
   CallCreateInstance("lcomp.dll");            
   LUnknown* pIUnknown = CreateInstance(slot);
   if(pIUnknown == NULL) { trace("CallCreateInstance failed"); return 1; }
   
   trace("Get IDaqLDevice interface");
   IDaqLDevice* pI;
   HRESULT hr = pIUnknown->QueryInterface(IID_ILDEV,(void**)&pI);      //    [B]из dll-ки[/B]
   if(!SUCCEEDED(hr)) { trace("Get IDaqLDevice failed"); return 1; }
   trace("IDaqLDevice get success");
   trace("Free IUnknown");
   pIUnknown->Release();                //    [B]из dll-ки[/B]

   printf("\n handle %x",pI->OpenLDevice());         //    [B]из dll-ки[/B]



функция CallCreateInstance :

Код

ULONG CallCreateInstance(char* name)
{
   HINSTANCE hComponent = ::LoadLibrary(name);
   if(hComponent==NULL)
   {
//      cout << "Unable load dll" << endl;
      return 0;
   }

   CreateInstance = (CREATEFUNCPTR)::GetProcAddress(hComponent,"CreateInstance");
   if(CreateInstance==NULL)
   {
//      cout << "Unable find CreateInstance" << endl;
      return 0;
   }
   return 1;
}


Автор: Exception 27.1.2006, 22:04
Библиотека совместима с OLE Automation? Если нет, на помощь врапперов не рассчитывай.

Автор: qpeHukc 28.1.2006, 00:13
Цитата(Exception @ 27.1.2006, 22:04)
Библиотека совместима с OLE Automation? Если нет, на помощь врапперов не рассчитывай.

есть пример работы с этой библиотекой на Delphi.

значит совместима, так ведь ?

Автор: Exception 28.1.2006, 01:05
Не факт. Кинь dll, посмотрим.

Автор: qpeHukc 28.1.2006, 01:31
вот оно

Автор: mr.DUDA 28.1.2006, 08:37
Враппер создать не получилось. Похоже на простейший COM-компонент. Всё что можно сделать, имхо, это скопировать все структуры и интерфейсы в код на C#, а все импортируемые ф-ции вынести с атрибутами [DllImport] в отдельный класс.

Автор: qpeHukc 28.1.2006, 10:22
Цитата(mr.DUDA @ 28.1.2006, 08:37)
Враппер создать не получилось. Похоже на простейший COM-компонент. Всё что можно сделать, имхо, это скопировать все структуры и интерфейсы в код на C#, а все импортируемые ф-ции вынести с атрибутами [DllImport] в отдельный класс.

ясно

а как выносить типы ?

например ULONG в C# это ulong, а что делать с

void** ppv
const IID& iid
PUCHAR
HRESULT
PUSHORT Data ( может это равно ref ushort ?)
char *FileName

Автор: mr.DUDA 28.1.2006, 10:25
IID - это Guid
PUCHAR , char* - это byte*
HRESULT - HandleRef
PUSHORT - ushort*

С указателями в C# можно работать, если поставить у метода модификатор unsafe и выставить у проекта "Allow unsafe code". Вообще, строки при вызове функций из длл автоматически переводятся из char* в string и обратно.

Автор: qpeHukc 30.1.2006, 23:45
не выходит с переделками типов.

было :

Код

IFC(HRESULT)   QueryInterface(const IID& iid, void** ppv) = 0; 


сделал :

Код

[DllImport("lcomp.dll",CallingConvention=CallingConvention.StdCall)] extern static
        public HandleRef QueryInterface(Guid iid, IntPtr i);


вызвал :

Код

Guid helperGuid = new Guid("32bb8320-b41b-11cf-a6bb-0080c7b2d682");
IntPtr intPtrVar = new IntPtr();

LUnknown.QueryInterface(helperGuid, intPtrVar);


пишет MarshalDirectiveException was unhandled

HandleRefs cannot be marshaled ByRef or from unmanaged to managed.

smile

в чем ссуть ?

Автор: mr.DUDA 31.1.2006, 17:04
Пардон, я спутал - HandleRef нужен только для передачи и возврата виндошных дескрипторов aka хэндлов.
HRESULT хоть и начинается с H, но не хэндл smile
Обыкновенный Int32

Автор: qpeHukc 31.1.2006, 23:22
а можно как-то глянуть что происходит в dll - ке ?

теперь при вызове функции появляется EntryPointNotFoundException : Unable to find an entry point named 'QueryInterface' in DLL 'lcomp.dll'.

искал в инете что-то подобное, нашел просто повтор в параметре EntryPoint имени функции. Сделал так-же -
Код

[DllImport("lcomp.dll",EntryPoint="QueryInterface")] public static extern
        Int32 QueryInterface(Guid iid, IntPtr i);
, но не помогло

Автор: qpeHukc 1.2.2006, 20:55
Нашел вот такое описание библиотеки : Библиотека LCOMP под Windows'98/Me/2000/XP. Она построена на основе современных WDM-драйверов...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)