Импорт функций из библиотеки на c/c++ в VB.

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Gogic
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 24.08.2008 (Вс) 13:19

Импорт функций из библиотеки на c/c++ в VB.

Сообщение Gogic » 18.02.2013 (Пн) 13:34

Добрый день.

В библиотеке на с++ есть функция такого вида:

Код: Выделить всё
BOOL GetCPUName   (   LPWSTR    lpszCpuName,
SIZE_T    Size
)


Пробовал объявлять ее всяко, например так:
Код: Выделить всё
Public Declare Function GetCPUName Lib "aspia.dll" (ByRef lpszCpuName As String, ByRef Size As Long) As Boolean


Экспериментировал с разными вариантами... Я понимаю, конечно, что LPWSTR - это не String, у кого какие соображения?

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 18.02.2013 (Пн) 13:44

Есть соображения, что она cdecl на самом деле...

Gogic
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 24.08.2008 (Вс) 13:19

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Gogic » 18.02.2013 (Пн) 15:47

Есть соображения, что она cdecl на самом деле...


То есть из vb ее не вызвать, получается?

нашел любопытную вещь, читаю.
viewtopic.php?f=54&t=44385

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Хакер » 18.02.2013 (Пн) 15:55

Gogic писал(а):Я понимаю, конечно, что LPWSTR - это не String

LPWSTR это ближе всего к String-у. Только не надо пользоваться Declare.
ByRef в обоих параметрах — это чушь. Необосновнная (при всей фантазии не удастся придумать обосновании) ахинея. Должен быть ByVal в обоих. Это не угадайка же, чтобы «пробовать все варианты».
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Gogic
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 24.08.2008 (Вс) 13:19

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Gogic » 18.02.2013 (Пн) 16:26

Хакер писал(а): Только не надо пользоваться Declare.
ByRef в обоих параметрах — это чушь. Необосновнная (при всей фантазии не удастся придумать обосновании) ахинея. Должен быть ByVal в обоих. Это не угадайка же, чтобы «пробовать все варианты».


1. Поподробнее, пожалуйста, как не пользоваться Declare.

2. ByRef (Visual Basic)
Указывает такой способ передачи аргумента, при котором вызванная процедура может изменить значение переменной, содержащейся в аргументе вызывающего кода.

Разве переменная, которую требуется получить не находится в аргументе?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Хакер » 18.02.2013 (Пн) 16:31

Gogic писал(а):1. Поподробнее, пожалуйста, как не пользоваться Declare.

Объявить в TLB.

Gogic писал(а):Разве переменная, которую требуется получить не находится в аргументе?

Не требуется получать переменную. Это даже практически бессмысленная фраза.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Gogic
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 24.08.2008 (Вс) 13:19

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Gogic » 18.02.2013 (Пн) 16:54

Хакер писал(а):Объявить в TLB. Не требуется получать переменную. Это даже практически бессмысленная фраза.


Ну, с TLB заморачиваться точно не буду, буду искать другие варианты.

Кстати, вот так работает и из среды, правда ничего не возвращает, но и не вываливается.
Код: Выделить всё
Public Declare Function GetCPUName CDecl Lib "aspia.dll" (ByRef lpszCpuName As String, ByVal Size As Long) As Boolean

Код: Выделить всё
Private Sub Command1_Click()
Dim xyz
Debug.Print GetCPUName(VarPtr(xyz), 100)
Debug.Print xyz, Len(xyz)
End Sub


Почему нужно использовать ByVal, я так и не понял, видимо не для моих мозгов...

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Хакер » 18.02.2013 (Пн) 17:04

Gogic писал(а):Ну, с TLB заморачиваться точно не буду, буду искать другие варианты.

Надо. Остальные варианты паршивы и тошнотоврны.

Gogic писал(а):Private Sub Command1_Click()
Dim xyz
Debug.Print GetCPUName(VarPtr(xyz), 100)
Debug.Print xyz, Len(xyz)
End Sub

Это дрянь и чушь, бред и маразм.
Переменная имеет тип Variant, а должна иметь String.
Вместо VarPtr должна была применяться StrPtr по отношению к строке.
Вместо ByRef lpszCpuName As String в вышеуказанном примере должно было бы быть ByVal lpszCpuname As Long. В противном случае передаётся указатель на строковое представление адреса Variant-переменной. Давно не видел таких бессмысленных ивзратов.
Строковая переменная должна инициализироваться какой-то строкой какой-то заведомо большой длины чтобы образовать буфер, который будет переписан поверх новыми данными.
За жестко вшитую константу «сто» надо отрезать руки. Должна быть не жестко вшитая константа, а константа, соответствующая размеру прединициализированного буфера.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Хакер » 18.02.2013 (Пн) 17:10

Gogic писал(а):Почему нужно использовать ByVal, я так и не понял, видимо не для моих мозгов...

Почему не для твоих? Для любых.
Вызываемая функция должна получить [указатель на строку], а не [указатель на [указатель на строку]].
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Gogic
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 24.08.2008 (Вс) 13:19

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Gogic » 18.02.2013 (Пн) 18:24

Хакер писал(а):Почему не для твоих? Для любых.
Вызываемая функция должна получить [указатель на строку], а не [указатель на [указатель на строку]].


Спасибо, уже понял все из предыдущего поста.

Теперь при вызове из среды она вываливается, а если скомпилировать, сама функция возвращает значение 22528.
Хотя строка xyz все равно нулевой длины.
Код: Выделить всё
Public Declare Function GetCPUName CDecl Lib "aspia.dll" (ByVal lpszCpuName As Long, ByVal Size As Long) As Boolean
Dim xyz As String
Dim buff As Long

Private Sub Command1_Click()
buff = 1000
Print GetCPUName(StrPtr(xyz), buff)
Print xyz, Len(xyz)
End Sub


Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 18.02.2013 (Пн) 18:29

Потому что строку надо заполнять сначала?

Gogic
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 120
Зарегистрирован: 24.08.2008 (Вс) 13:19

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Gogic » 18.02.2013 (Пн) 19:07

Qwertiy писал(а):Потому что строку надо заполнять сначала?


Код: Выделить всё
xyz = Space(255)


255 пробелов теперь возвращает.

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Импорт функций из библиотеки на c/c++ в VB.

Сообщение Vi » 21.02.2013 (Чт) 8:58

Dynamic Call с исходниками или поищи на форуме или в Интернете DynaCall или DynaWrap.

Оттуда:
const ARGTYPEINFO ArgInfo[] =
{
{'c', sizeof(unsigned char), VT_UI1}, // cC BYTE bVal
{'i', sizeof(short), VT_I2}, // iI SHORT iVal
{'l', sizeof(long), VT_I4}, // lL LONG lVal
{'h', sizeof(long), VT_I4}, // hH HANDLE lVal
{'u', sizeof(UINT), VT_I4}, // uU UINT lVal
{'f', sizeof(float), VT_R4}, // fF FLOAT fltVal
{'d', sizeof(double), VT_R8}, // dD DOUBLE dblVal
{'b', sizeof(VARIANT_BOOL), VT_BOOL}, // bB VARIANT_BOOL boolVal
{'k', sizeof(IUnknown*), VT_UNKNOWN}, // kK LPUNKNOWN punkVal
{'o', sizeof(IDispatch*), VT_DISPATCH}, // oO LPDISPATCH pdispVal
{'s', sizeof(LPSTR), VT_LPSTR}, // sS string bstrVal
{'w', sizeof(LPWSTR), VT_LPWSTR}, // wW wstring bstrVal
{'v', sizeof(VARIANT), VT_VARIANT}, // vV VARIANT pvarVal
{'t', sizeof(DATE), VT_DATE}, // tT DATE date

{'p', sizeof(void*), VT_BYREF}, // pP pointer byref

{'r', sizeof(LPSTR), VT_LPSTR}, // rR out string same as S
};

Поэтому BOOL GetCPUName(LPWSTR lpszCpuName, SIZE_T Size) обработается как
Код: Выделить всё
With CreateObject("DynamicWrapper")
  .Register "C++.DLL", "GetCPUName", "F=MC", "I=WL", "R=L"

' ...

  buff = 1000
  xyz = String(buff, "")
  .GetCPUName xyz, buff
End With

Возможно, придётся обработать С++ преобразованное имя: оно может быть достаточно сложным.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Majestic-12 [Bot] и гости: 65

    TopList