Страница: 1 |
Страница: 1 |
Вопрос: Подключение Си DLL к VB.NET
Добавлено: 30.06.05 15:31
Автор вопроса: Ruslan_x
Есть 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
Автор ответа:
freeloader
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
Автор ответа:
Ruslan_x
Вопросов: 7
Ответов: 41
Профиль | | #3
Добавлено: 01.07.05 06:12
Спасибо, функцию я подключил. Однако осталось проблема - как передать строку из VB.NET в DLL?
Ведь форматы строк в VB.NET и в Си разный.
Есть пара функций, которые требуют строковых переменных. Вот кусок декларации из под C++:
...(char * s)
Просто объявить в VB.NET ...(s As String) и передать строку в обычном виде не получилось.
Номер ответа: 4
Автор ответа:
freeloader
ICQ: 50804884
Вопросов: 72
Ответов: 642
Web-сайт:
Профиль | | #4
Добавлено: 01.07.05 06:37
а если попробовать "s as char"?
Номер ответа: 5
Автор ответа:
GSerg
Вопросов: 0
Ответов: 1876
Профиль | | #5
Добавлено: 01.07.05 06:51
byval s as string.
При этом посмотреть, какая кодировка указана в атрибутах маршалинга при объявлении функции.
Номер ответа: 6
Автор ответа:
Ruslan_x
Вопросов: 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
Автор ответа:
GSerg
Вопросов: 0
Ответов: 1876
Профиль | | #7
Добавлено: 01.07.05 11:31
Ышшо раз...
ByVal As String, а не ByRef As String.
Номер ответа: 8
Автор ответа:
Ruslan_x
Вопросов: 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
Автор ответа:
GSerg
Вопросов: 0
Ответов: 1876
Профиль | | #9
Добавлено: 01.07.05 13:18
(ByVal s As String, ByVal buf As String) As Short
А теперь покажи, как вызываешь.
Номер ответа: 10
Автор ответа:
Ruslan_x
Вопросов: 7
Ответов: 41
Профиль | | #10
Добавлено: 01.07.05 13:42
Объявление:
Declare Auto Function BuildNormalForms Lib "MAD.dll" _
 ByVal s As String, ByVal buf As String) As Short
End Class
Вызов:
Dim s As String = "пример"
Dim buf As String = ""
num = func.BuildNormalForms(s, buf)
Номер ответа: 11
Автор ответа:
Ruslan_x
Вопросов: 7
Ответов: 41
Профиль | | #11
Добавлено: 01.07.05 14:32
Позор на мою глупую голову!
Пропустил важное слово "Ansi".
Надо не:
Declare Auto Function BuildNormalForms...
а:
Declare Ansi Function BuildNormalForms...
Сейчас функция выдает правильный результат, пойду разбираться с более сложными структурами.
GSerg, огромное спасибо за подсказку! Очень выручил.
Номер ответа: 12
Автор ответа:
Ruslan_x
Вопросов: 7
Ответов: 41
Профиль | | #12
Добавлено: 02.07.05 08:10
К DLL информация проходит, а обратно - нет.
Объясняю.
Функция работает и выдает целое число - 0,1 или 2, которое соответствует кол-ву найденных форм.
А сами эти формы "в виде повторяющихся строк, заканчивающихся нулевым символом" возвращаются в переменной buf.
Вот как я объявлюя функцию:
 eclare Ansi Function BuildNormalForms Lib "MAD.dll" _
 ByVal s As String, ByVal buf As String) As Short
End Class
Как видно, переменная buf объявлена ByVal. Результат - там ничего не возвращается.
Пробую сделать ByRef - получаю ошибку "Object reference not set to an instance of an object."
Похоже, что нужно как-то хитро обработать эту buf, чтобы получать значения от DLL. Но вот как?....
Номер ответа: 13
Автор ответа:
GSerg
Вопросов: 0
Ответов: 1876
Профиль | | #13
Добавлено: 02.07.05 08:50
Чел...
Почитай про азы работы с API, а?
buf ты должен сначала выделить.
А потом вызвать функцию.
Только позырь сначала в документации, каков должен быть размер этого buf, потому что 100 - это от балды...
Номер ответа: 14
Автор ответа:
Ruslan_x
Вопросов: 7
Ответов: 41
Профиль | | #14
Добавлено: 02.07.05 19:27
Спасибо за подсказку.
Проблему решил так:
Объявление:
Declare Ansi Function BuildNormalForms Lib "MAD.dll" _
 ByVal s As String, ByVal b() As Byte) As Short
End Class
Вызов:
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
Автор ответа:
Greis
Вопросов: 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 "LL.h"
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
Пожалуйста подскажите, где ошибка...?