Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 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-сайт: freeloader.folder-pro.net
 Профиль | | #1
Добавлено: 30.06.05 17:00
бррррр ну и страсти, как же на этом Си еще программируют...

сорри за оффтоп, просто возмутительно не нравится мне синтаксис...

Ответить

Номер ответа: 2
Автор ответа:
 Павел



Администратор

ICQ: 326066673 

Вопросов: 368
Ответов: 5968
 Web-сайт: www.vbnet.ru
 Профиль | | #2
Добавлено: 30.06.05 19:02
Для вызова функций из unmanaged библиотек используйте атрибут
DLLImport... ВОт пример из MSDN:

<;DllImport("KERNEL32.DLL", EntryPoint := "MoveFileW", _
   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-сайт: freeloader.folder-pro.net
 Профиль | | #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
Declare Ansi Function BuildNormalForms Lib "MAD.dll" _
(ByVal s As String, ByVal buf As String) As Short


А теперь покажи, как вызываешь.

Ответить

Номер ответа: 10
Автор ответа:
 Ruslan_x



Вопросов: 7
Ответов: 41
 Профиль | | #10 Добавлено: 01.07.05 13:42
Объявление:
    Public Class func
        Declare Auto Function BuildNormalForms Lib "MAD.dll" _
        ;(ByVal s As String, ByVal buf As String) As Short
    End Class


Вызов:
        Dim num As Short
        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.

Вот как я объявлюя функцию:
Public Class func
        ;Declare 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=new string(chr(0), 100)

А потом вызвать функцию.


Только позырь сначала в документации, каков должен быть размер этого buf, потому что 100 - это от балды...

Ответить

Номер ответа: 14
Автор ответа:
 Ruslan_x



Вопросов: 7
Ответов: 41
 Профиль | | #14 Добавлено: 02.07.05 19:27
Спасибо за подсказку.

Проблему решил так:

Объявление:
    Public Class func
        Declare Ansi Function BuildNormalForms Lib "MAD.dll" _
        ;(ByVal s As String, ByVal b() As Byte) As Short
    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
Автор ответа:
 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 ";DLL.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

Пожалуйста подскажите, где ошибка...?

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам