Получить структуры из DLL без промежуточного кода - C#

Узнай цену своей работы

Формулировка задачи:

Есть нативная длл. Для работы с длл необходимо написать программу на С# . Имеется описание структур. там их много, укажу только две.
#ifndef __IFactory_h__
#define __IFactory_h__
struct  IFactory
{
    virtual void* __stdcall Create(TCHAR*, void*) = 0;
};
#endif
struct  IEasyDriver
{
    virtual unsigned __stdcall  AddRef() = 0;
    virtual unsigned __stdcall  Release() = 0;
 
//  return >  0 if success
//  return == 0 if operation not support
//  return <  0 if error, return IEASYDRIVER_ERROR_... code, call GetLastError() function for details
    virtual int      __stdcall  IO(ParametersBase*) = 0;
};
Пример С++:
    IFactory*           PCIFactory = NULL;
    IEasyDriver*        m_pPCI     = NULL;
    
    //  здесь LoadLibrary(szPath);
 
    //Загружаем драйвер устройства 
    PCIFactory = (IFactory*)GetProcAddress(m_hLib, szExportName);
 
    if(PCIFactory == 0)//Если устройство не загрузилось
    {
        cout<<"Can not load device"<<endl;
        return 0;
    }
 
    //Создаем интерфейс для работы с драйвером
    m_pPCI = (IEasyDriver*)PCIFactory->Create(_T("IEasyDriver"), 0);
 
   if(m_pPCI == 0)//Если интерфейс не создался
   {
       cout<<"Can not create IEasyDriver"<<endl;   
       return 0;
   }
Смотрим длл утилитой dumpbin ordinal hint RVA name 3 0 00001A40 DllRegisterServer 4 1 00001B50 DllUnregisterServer 1 2 000125B4

StaticFactory

2 3 000019D0 _DllMain@12 Сможем получить только указатель на структуру, больше ничего не экспортируется. Реализации методов у нас нет. Как быть? Написал промежуточный код на С++ ,точнее на C++/CLI для удобства, но не важно получилась дополнительная сборка.
#include  "IEasyDriver.h"
#include  "IFactory.h"
#include  "WrEasyDriver.h"
#include  "MeConvert.h"
 
using namespace System;
 
public ref class WrFactory
{
private:
    IFactory * pFactory;

public: WrFactory(IFactory * _pFactory)
    {
         pFactory =  _pFactory;
    }
        
    WrFactory(IntPtr _ptr)
    {
         pFactory =  static_cast<IFactory *>(_ptr.ToPointer());
    }
 
    WrFactory()
    {
         pFactory =  0;
    }
    public:
    static  WrFactory^ PtrToFactory(IntPtr _ptr)
      {   
          return gcnew WrFactory(_ptr);
      }
 
    WrEasyDriver^  Create( System::String^ InterfaceName, System::IntPtr pReserved)
    {
        if( !pFactory)
            return nullptr;
 
        char chInterfaceName[100];
        MeConvert::ConvertStr(InterfaceName,chInterfaceName);
        IEasyDriver* pEasyDriver =  static_cast<IEasyDriver*>( pFactory->Create(chInterfaceName,0));
 
        return gcnew WrEasyDriver(pEasyDriver);
    }
}; #pragma once
#include  "WrParametersBase.h"
#include  "IEasyDriver.h"
 
using namespace System;
 
public ref class WrEasyDriver
 
{ 
    IEasyDriver* pEasydriver;
public:
    WrEasyDriver(IntPtr _ptr)
    {
         pEasydriver = static_cast<IEasyDriver*>(_ptr.ToPointer());
    }

    WrEasyDriver(IEasyDriver* _pEasydriver)
    {
         pEasydriver =  _pEasydriver;
    }
    public: WrEasyDriver()
    {
         pEasydriver =  0;
    }

    static  WrEasyDriver^ PtrToDriver(IntPtr _ptr)
      {   
          return gcnew WrEasyDriver(_ptr);
      }
 
public:  unsigned  AddRef()
     {   
         if(  !  pEasydriver )
             return 0;
       return  pEasydriver->AddRef();
     }
 
public:   unsigned  Release()
     {   
          if(  !  pEasydriver )
             return 0;
       return  pEasydriver->Release();
     }

    //  return >  0 if success
    //  return == 0 if operation not support
    //  return <  0 if error, return IEASYDRIVER_ERROR_... code, call GetLastError() function for details
    //virtual int      __stdcall  IO(ParametersBase*) = 0;
 
public:  int IO(IParametersBase^ _iParametersBase)
     {      
         ParametersBase  paramBase;
         paramBase.m_nType = _iParametersBase-> m_nType;
         paramBase.m_nSizeOf = _iParametersBase->m_nSizeOf;
         return  pEasydriver->IO(&paramBase);
     }
 
};
И это работает
       WrFactory PCIFactory = null;
        WrEasyDriver m_pPCI = null;

        IntPtr m_hLib;
        string szPath = "SampleDLL.dll";
        string szExportName = "StaticFactory";
 
        m_hLib = LoadLibrary(szPath);
        if (m_hLib == IntPtr.Zero)
        {
            Console.WriteLine("Can not load Library");
            FreeLibrary(m_hLib);
            return;
        }

        IntPtr ptfactory = (IntPtr)GetProcAddress(m_hLib, szExportName);
 
        PCIFactory = WrFactory.PtrToFactory(ptfactory);
 
        if (PCIFactory == null)//Если устройство не загрузилось
        {
            Console.WriteLine("Can not load device");
            FreeLibrary(m_hLib);
            return;
        }
        else
            Console.WriteLine("device loaded.");
        //
        //    //Создаем интерфейс для работы с драйвером
        m_pPCI = (WrEasyDriver)PCIFactory.Create("IEasyDriver", IntPtr.Zero);
 
        if (m_pPCI == null)//Если интерфейс не создался
        {
            
            Console.WriteLine("Can not create IEasyDriver");
            FreeLibrary(m_hLib);
            return;
        }
        else
            Console.WriteLine("IEasyDriver created.");
Вывод : Device loaded. IEasyDriver created. Так вот вопрос : Можно ли обойтись без промежуточного кода, Сделать все силами С# без промежуточных ДЛЛ ?

Решение задачи: «Получить структуры из DLL без промежуточного кода»

textual
Листинг программы
[ComImport, Guid("6981C3CD-1874-40E4-9B1F-E998171A9B7C")]
class ProxyClass
{
}
 
void Main()
{
    var proxyClass = new ProxyClass();
    var obj = (ISampleInterface)proxyClass;
    obj.SampleMethod();
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 3.833 из 5