2016-11-10 3 views
0

У меня есть сторонняя DLL, в которой я пытаюсь написать оболочку на C# и есть код примера C++, который работает, но когда я пытаюсь позвонить методы в DLL, я получаю ошибку:Методы вызова в C++ dll из C# без какой-либо информации, только файлы заголовков

Не удалось найти точку входа с именем 'scan' в DLL 'scard-com.dll'.

Пожалуйста, помогите указать мою проблему:

Вот часть .h файла, используемого в образце C++ приложение

interface ISCard_CardReaderDevices : IUnknown { 
virtual UINT __stdcall scan(void) = 0; 
virtual UINT __stdcall getDeviceCount(void) = 0; 
virtual const CHAR * __stdcall getDeviceName(UINT id) = 0; 
virtual const CHAR * __stdcall getSerialName(UINT id) = 0; 
virtual ISCard_CardReader * __stdcall connectById(UINT id) = 0; 
virtual ISCard_CardReader * __stdcall connectByName(const CHAR *name) = 0; 
virtual ISCard_CardReader * __stdcall connectBySerial(const CHAR *serial) = 0; 
virtual BOOL __stdcall disconnect(ISCard_CardReader *reader) = 0; 
virtual ISCard_SecMsg * __stdcall attachSecMsg(ISCard_CardReader *reader) = 0; 
virtual void __stdcall detachSecMsg(ISCard_SecMsg *secMsg) = 0; 
virtual ISCard_Script * __stdcall attachScript(ISCard_CardReader *reader) = 0; 
virtual void __stdcall detachScript(ISCard_Script *script) = 0; 
virtual ISCard_IsoCard * __stdcall attachIsoCardByReader(ISCard_CardReader *reader) = 0; 
virtual ISCard_IsoCard * __stdcall attachIsoCardBySecMSG(ISCard_SecMsg *secMsg) = 0; 
virtual void __stdcall detachIsoCard(ISCard_IsoCard *isocard) = 0; 
virtual ISCard_MTCOS * __stdcall attachMTCOSByReader(ISCard_CardReader *reader) = 0; 
virtual ISCard_MTCOS * __stdcall attachMTCOSBySecMSG(ISCard_SecMsg *secMsg) = 0; 
virtual void __stdcall detachMTCOS(ISCard_MTCOS *os) = 0; 
virtual ISCard_IcaoConverter * __stdcall attachIcaoConverter(void) = 0; 
virtual void __stdcall detachIcaoConverter(ISCard_IcaoConverter *icaoconv) = 0; 
virtual ISCard_ImageConverter * __stdcall attachImageConverter(void) = 0; 
virtual void __stdcall detachImageConverter(ISCard_ImageConverter *imgconv) = 0; 
#ifdef MULTIAPP_EXT 
virtual ISCard_IDLConverter * __stdcall attachIDLConverter(void) = 0; 
virtual void __stdcall detachIDLConverter(ISCard_IDLConverter *idlconv) = 0; 
virtual ISCard_sscdConverter * __stdcall attachSSCDConverter(void) = 0; 
virtual void __stdcall detachSSCDConverter(ISCard_sscdConverter *sscdconv) = 0; 
virtual ISCard_eHealthConverter * __stdcall attacheHealthConverter(void) = 0; 
virtual void __stdcall detacheHealthConverter(ISCard_eHealthConverter *eHealthconv) = 0; 
#endif // MULTIAPP_EXT 
}; 

В моем проекте C#, я добавил этот класс:

public class SCardWrapper 
{ 
    [DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern uint scan(); 

// And call it like this: 

public int listReaders() 
    { 
     try 
     { 
      uint numreaders = scan(); 
      if (numreaders < 1) 
      { 
       return 0; 
      } 
      for (int i = 0; i < numreaders; i++) 
      { 
       IntPtr iDevice = getDeviceName(uint.Parse(i.ToString())); 
       String sDevice = Marshal.PtrToStringAuto(iDevice); 
       Debug.WriteLine(string.Format("{0} : " + sDevice, i)); 
      } 
      return int.Parse(numreaders.ToString()); 
     } 
     catch 
     { 
      return -1; 
     } 
    } 
} 

Но как только он попадает в метод scan(), я получаю ошибку выше. Любая помощь будет оценена!

+1

В части заголовка, который вы опубликовали, нет 'scan'. – Chris

+0

Слово «COM» в имени DLL примечательно. Как и объявление в заголовке, это COM-интерфейс. Нет, они не экспортируют эти функции. Вы просто добавляете ссылку на библиотеку типов. Обычно встраивается в самую DLL, поэтому используйте Project> Add Reference> Browse button> select scard-com.dll. –

+0

Извините, добавлено неверное описание интерфейса, отредактированный пост, чтобы показать правильный. – Thys

ответ

0

Такое scan заявление:

public class SCardWrapper 
{ 
    [DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern uint scan(); 
} 

является обязательным для функции с именем scan из DLL scard-com.dll. Убедитесь, что эта функция находится в вашем DLL-интерфейсе scard-com.dll. Для этого вы можете использовать Dependency Walker.

scan имя может быть mangled в вашей DLL. В этом случае вы можете определить его как extern "C" в неуправляемом коде или добавить EntryPoint = "mangled_scan_name" в свою декларацию PInvoke.

К сожалению, scan не является частью interface ISCard_CardReader. Но если это метод класса, то неправильный CallingConvention = CallingConvention.Cdecl.

1

P/Invoke не действительно поддержка C++. Вы пытаетесь вызвать метод на интерфейсе, а не функцию C-стиля.

Есть некоторые хаки, которые могут получить нужные вам результаты, но, как правило, лучшим вариантом является создание библиотеки взаимодействия C++/CLI, которую вы можете использовать из своего проекта C#.

Также, как правило, заголовочных файлов недостаточно для правильного вызова родной библиотеки. Вам нужна документация: вам нужно держать руку на таких проблемах, как «Насколько большой должен быть строковый буфер? Кто несет ответственность за выделение/освобождение памяти? Что происходит, когда буфер недостаточно велик? условия ошибки? " Если у вас нет документации, вы можете немного поработать, но наслаждайтесь обратным проектированием :)

Смежные вопросы