Страница: 1 |
Вопрос: Подключение Си DLL к VB.NET | Добавлено: 30.06.05 15:31 |
Автор вопроса: ![]() |
Есть DLL, написанная на Си. И есть пример программы на С++, который использует эту DLL.
Вопрос - можно ли как-нибудь подсмотреть в С++ синтаксис вызова функции из DLL и перенести это все на почву VB.NET? Для меня C++ - темный лес, но тем не менее я честно пытался разобраться со страшными конструкциями типа: ------------- void CTest_mtlemmDlg::OnTest1() { HINSTANCE hLib = LoadLibrary("mtlemm.dll"); ASSERT(hLib); DWORD (CALLBACK* pfnMtLemmFunc1)(byte *buff, byte *datapath, struct TMorfAnswer *TMorfAnswerPtr); (FARPROC&)pfnMtLemmFunc1 = GetProcAddress(hLib, "MtLemmFunc1"); ASSERT(pfnMtLemmFunc1); byte buff[] = "code"; struct TMorfAnswer TMorfAnswer1[100]; int res = pfnMtLemmFunc1 (buff, "", &TMorfAnswer1[0]); FreeLibrary(hLib); } ------------- Однако, через несколько десятков неудачных попыток обратиться к mtlemm.dll из VB.NET до меня дошло, что нужно обратиться к специалистам. К автору DLL я уже обращался, но он сам пишет только на Си и ничем помочь не может. Те, кто заинтересуются, могут взглянуть на DLL с программой на C++, про которую я говорю: http://www.multitran.ru/DownLoad/lemm.zip |
Ответы | Всего ответов: 15 |
Номер ответа: 1 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 50804884 Вопросов: 72 Ответов: 642 |
Web-сайт: Профиль | Цитата | #1 | Добавлено: 30.06.05 17:00 |
бррррр ну и страсти, как же на этом Си еще программируют...
сорри за оффтоп, просто возмутительно не нравится мне синтаксис... |
Номер ответа: 2 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ![]() Администратор ICQ: 326066673 Вопросов: 368 Ответов: 5968 |
Web-сайт: Профиль | Цитата | #2 | Добавлено: 30.06.05 19:02 |
Для вызова функций из unmanaged библиотек используйте атрибут
DLLImport... ВОт пример из MSDN: <
![]() SetLastError := True, CharSet := CharSet.Unicode, _ ExactSpelling := True, _ CallingConvention := CallingConvention.StdCall)> _ Public Shared Function MoveFile(src As String, dst As String) As Boolean ' Leave function empty - DLLImport attribute forwards calls to MoveFile to ' MoveFileW in KERNEL32.DLL. End Function |
Номер ответа: 3 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #3 | Добавлено: 01.07.05 06:12 |
Спасибо, функцию я подключил. Однако осталось проблема - как передать строку из VB.NET в DLL?
Ведь форматы строк в VB.NET и в Си разный. Есть пара функций, которые требуют строковых переменных. Вот кусок декларации из под C++: ...(char * s) Просто объявить в VB.NET ...(s As String) и передать строку в обычном виде не получилось. |
Номер ответа: 4 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 50804884 Вопросов: 72 Ответов: 642 |
Web-сайт: Профиль | Цитата | #4 | Добавлено: 01.07.05 06:37 |
а если попробовать "s as char"? |
Номер ответа: 5 Автор ответа: ![]() ![]() ![]() Вопросов: 0 Ответов: 1876 ![]() |
Профиль | Цитата | #5 | Добавлено: 01.07.05 06:51 |
byval s as string.
При этом посмотреть, какая кодировка указана в атрибутах маршалинга при объявлении функции. |
Номер ответа: 6 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #6 | Добавлено: 01.07.05 10:48 |
Так я ж могу любую кодировку указать при объявлении функции в VB.NET...
Ну вот самая простая функция. Это информация из .h файла, который шел к MAD.DLL: ------------------------------ // Функция возвращает число построенных // нормальных форм слова s. Если возвращено нулевое значение, то слово в словаре не найдено. // Результат работы возвращается в буфере buf в виде повторяющихся строк, заканчивающихс // нулевым символом (строка в формате Си). int MDDLL_EXP BuildNormalForms(const char *s, const char *buf); ------------------------------ Объявляю я ее в VB.NET так: ------------------------------ Public Class func Declare Auto Function BuildNormalForms Lib "MAD.dll" _ (ByVal s As String, ByRef buf As String) As Short End Class ------------------------------ Можно, конечно использовать более сложный синтакс, для вызова (предложенный Павлом), но этот тоже работает. При тестировании функция нормально загружается, но возвращает всегда только 0, не зависимо от того, какое слово s я ей подсуну. Тут же в директории есть экзешник, который обращается к этой MAD.dll и там все работает нормально на любых словах (они считываются с txt файла). Таким образом, становится очевидным, что функция просто не понимает строку s, которую ей передает VB.NET. Вопрос - как привести строку s в вид, который бы устроил DLL. ------------------- В инете вычитал такую информацию: Strings in VB.NET are unicode characters (16 bits) but strings in VC6 C++ are null terminated ASCII strings. So you must encode the bytes arrays to become VB.NET strings. Похоже, что нужно как-то преобразовать строку, но как - до меня не до ходит... |
Номер ответа: 7 Автор ответа: ![]() ![]() ![]() Вопросов: 0 Ответов: 1876 ![]() |
Профиль | Цитата | #7 | Добавлено: 01.07.05 11:31 |
Ышшо раз...
ByVal As String, а не ByRef As String. |
Номер ответа: 8 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #8 | Добавлено: 01.07.05 11:40 |
Входной параметр - s - с самого начала был ByVal.
...Результат работы возвращается в буфере buf... То есть, я так понял, чтобы результат работы был доступен, то buf нужно объявлять ByRef. В любом случае, функция берет слово s и возвращает целое число - кол-во найденых форм. На buf на этом этапе можно вообще внимания не обращать. Но, возможно, я что-то не допонимаю. Поменял я на ByVal: (ByVal s As String, ByVal buf As String) Результат: те же яйца, только в профиль. Т.е. ничего не поменялось. |
Номер ответа: 9 Автор ответа: ![]() ![]() ![]() Вопросов: 0 Ответов: 1876 ![]() |
Профиль | Цитата | #9 | Добавлено: 01.07.05 13:18 |
Declare Ansi Function BuildNormalForms Lib "MAD.dll" _
(ByVal s As String, ByVal buf As String) As Short А теперь покажи, как вызываешь. |
Номер ответа: 10 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #10 | Добавлено: 01.07.05 13:42 |
Объявление:
Public Class func
Declare Auto Function BuildNormalForms Lib "MAD.dll" _ ![]() End Class Вызов: Dim num As Short
Dim s As String = "пример" Dim buf As String = "" num = func.BuildNormalForms(s, buf) |
Номер ответа: 11 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #11 | Добавлено: 01.07.05 14:32 |
Позор на мою глупую голову!
Пропустил важное слово "Ansi". Надо не: Declare Auto Function BuildNormalForms... а: Declare Ansi Function BuildNormalForms... Сейчас функция выдает правильный результат, пойду разбираться с более сложными структурами. GSerg, огромное спасибо за подсказку! Очень выручил. |
Номер ответа: 12 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #12 | Добавлено: 02.07.05 08:10 |
К DLL информация проходит, а обратно - нет. ![]() Объясняю. Функция работает и выдает целое число - 0,1 или 2, которое соответствует кол-ву найденных форм. А сами эти формы "в виде повторяющихся строк, заканчивающихся нулевым символом" возвращаются в переменной buf. Вот как я объявлюя функцию: Public Class func
![]() ![]() End Class Как видно, переменная buf объявлена ByVal. Результат - там ничего не возвращается. Пробую сделать ByRef - получаю ошибку "Object reference not set to an instance of an object." Похоже, что нужно как-то хитро обработать эту buf, чтобы получать значения от DLL. Но вот как?.... |
Номер ответа: 13 Автор ответа: ![]() ![]() ![]() Вопросов: 0 Ответов: 1876 ![]() |
Профиль | Цитата | #13 | Добавлено: 02.07.05 08:50 |
Чел...
Почитай про азы работы с API, а? ![]() buf ты должен сначала выделить. buf=new string(chr(0), 100)
А потом вызвать функцию. Только позырь сначала в документации, каков должен быть размер этого buf, потому что 100 - это от балды... |
Номер ответа: 14 Автор ответа: ![]() ![]() ![]() ![]() ![]() Вопросов: 7 Ответов: 41 |
Профиль | Цитата | #14 | Добавлено: 02.07.05 19:27 |
Спасибо за подсказку.
Проблему решил так: Объявление: Public Class func
Declare Ansi Function BuildNormalForms Lib "MAD.dll" _ ![]() End Class Вызов: Dim num As Short
Dim b() As Byte ReDim b(100) Dim s As String = "пример" num = func.BuildNormalForms(s, b) Dim ln As String = System.Text.Encoding.Default.GetString(b) В переменной ln имеем результаты работы функции в виде строк, отбитых Chr(0). На этом проблема решена. Еще раз - спасибо. |
Номер ответа: 15 Автор ответа: ![]() ![]() Вопросов: 1 Ответов: 1 |
Профиль | Цитата | #15 | Добавлено: 30.03.11 11:32 |
Вызов функции с параметрами из DLL(C++) в VB
Добрый день!) Помогите пожалуйста, не могу понять почему не работает... делаю тестовый пример. DLL.h #include <iostream.h> #include <stdio.h> #include <windows.h> extern "C" __declspec(dllexport) int Return4() ; extern "C" __declspec(dllexport) int Return5(int x); DLL.cpp #include " ![]() extern "C" __declspec(dllexport) int Return4() { int i; i=3; return i; } extern "C" __declspec(dllexport) int Return5(int x) { return x+1; } Вызов из VB. Private Declare Function Return5 Lib "H:\DLL\Debug\DLL.dll" (ByVal x As Integer) As Integer Private Declare Function Return4 Lib "H:\DLL\Debug\DLL.dll" () As Integer Private Sub CommandButton1_Click() TextBox1 = Return5(1) End Sub Private Sub CommandButton2_Click() TextBox1 = Return4() End Sub функция Return4 вызывается без проблем(которая без параметров), а вот, когда вызываешь Return5(с параметром) выдает ошибку(( Run-time eror '49' Bad DLL calling convention Пожалуйста подскажите, где ошибка...? |
Страница: 1 |
|