Подключение сторонней библиотеки на С++

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

Подключение сторонней библиотеки на С++

Сообщение strateg » 12.10.2010 (Вт) 15:43

Прикрепляю проект вызова двух функций из библиотеки по указателю. Функции служат для грамматического анализа слов и должны возвращать найденные простые составные части - лемы.

Первая функция возвращает первую найденную лему в буфер и с ней всё в порядке, а в переменную возвращает количество найденных лем.

Вторая функция должна вернуть дескриптор списка, с которым потом и надо работать дальше. Однако она не возвращает ничего, кроме нуля.

Делал на основании этой статьи
http://www.vbnet.ru/articles/Showarticle.aspx?id=204

Почему так происходит? Помогите разобраться.


Проект http://zalil.ru/29803724

1 Функция на С++ описана так
int sol_GetLemmaA( HLEM hEngine, const char * Word, char * Result, int BufSize )

2 функция
HLEMMAS sol_GetLemmasA( HLEM hEngine, const char * Word )
Выполняется лемматизация слова Word и все альтернативные варианты возвращаются в виде дескриптора списка. Для работы с этим списком далее описано несколько функций.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Re: Подключение сторонней библиотеки на С++

Сообщение Денис » 13.10.2010 (Ср) 8:19

Первое, что бросается в глаза: "Леммы" пишется с двумя "м".
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 13.10.2010 (Ср) 12:13

Да. Это конечно ценный совет. :wink:

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 13.10.2010 (Ср) 14:45

strateg писал(а):Делал на основании этой статьи http://www.vbnet.ru/articles/Showarticle.aspx?id=204

Судя по "Вызов функции – это помещение параметров в стек и выполнение процессорной команды call. Вот и всё. Существует несколько соглашений вызова (они определяют, как именно помещаются параметры в стек). Мы будем рассматривать только одно соглашение – StdCall. Во-первых, именно его используют все функции Windows, во-вторых, именно его использует VB." Для этого есть обычный Declare, который полностью решает проблему вызова таких функций.
strateg писал(а):1 Функция на С++ описана так
int sol_GetLemmaA( HLEM hEngine, const char * Word, char * Result, int BufSize )
2 функция
HLEMMAS sol_GetLemmasA( HLEM hEngine, const char * Word )
Выполняется лемматизация слова Word и все альтернативные варианты возвращаются в виде дескриптора списка. Для работы с этим списком далее описано несколько функций.

А они точно stdcall? Судя по заголовкам функций в ДЛЛ их имена человеческие, т.е. не перековерканы, значит, компилятору С++ помогают сформировать имена для вызова извне.
Код: Выделить всё
Public Declare Function GetLemma Lib "lemmatizator.dll" Alias "sol_GetLemmaA" (ByVal hEngine As Long, ByVal Word As String, ByVal Result As String, ByVal BufSize As Long) As Long

rez1 = GetLemma(rezlem, "простыни", resalt, 25)
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Re: Подключение сторонней библиотеки на С++

Сообщение SLIM » 13.10.2010 (Ср) 19:39

Vi писал(а):заголовкам функций в ДЛЛ их имена человеческие, т.е. не перековерканы, значит, компилятору С++ помогают сформировать имена для вызова извне.

Не факт
Пишите жизнь на чистовик.....переписать не удастся.....

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 14.10.2010 (Чт) 7:33

SLIM писал(а):Не факт

Код: Выделить всё
Private Declare Function LoadLemmatizator Lib "lemmatizator.dll" Alias "sol_LoadLemmatizatorA" (ByVal dbName As String) As Long
Private Declare Function GetLemma Lib "lemmatizator.dll" Alias "sol_GetLemmaA" (ByVal hEngine As Long, ByVal Word As String, ByVal Result As String, ByVal BufSize As Long) As Long
Private Declare Function GetLemmas Lib "lemmatizator.dll" Alias "sol_GetLemmasA" (ByVal hEngine As Long, ByVal Word As String) As Long

Private Sub Form_Load()
  Dim rezlem As Long, rez1 As Long, rez2 As Long
  Dim resalt As String
 
  rezlem = LoadLemmatizator("lemmatizer.db")
 
  'Эта функция возвращает в буфер количество лем - 3 и первую найденную
  resalt = String(25, " ")
  rez1 = GetLemma(rezlem, "простыни", resalt, 25)

  'Эта функция должна вернуть дескриптор списка, но ничего не возвращает
  rez2 = GetLemmas(rezlem, "простыни")

  Unload Me
End Sub

? hex(rezlem)
B5769D8
? rez1, len(resalt), resalt
3 25 ПРОСТЫНЯ
? hex(rez2)
B4DA108
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 14.10.2010 (Чт) 19:13

Спасибо, так работает.
Еще хотел спросить по поводу функции

int sol_GetLemmaW( HLEM hEngine, const wchar_t * Word, wchar_t * Result, int BufSize )


Я сделал так:
Private Declare Function GetLemmaW Lib "lemmatizator.dll" Alias "sol_GetLemmaW" (ByVal hEngine As Long, ByVal Word As String, ByVal Result As String, ByVal BufSize As Long) As Long


Потом вызываю так:
rez1 = GetLemmaW(rezlem, StrConv("простыни", vbFromUnicode), resalt, 25)


Возвращает только одну найденную лемму. Тогла как функция GetlemmaA возвращает 3.
Вероятно всё дело в типе данных
const wchar_t
я преобразовал в Юникод и это помогло найти одну лемму.

Может надо сделать как-то по-другому, чтобы нашлось 3 леммы?

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 15.10.2010 (Пт) 9:18

strateg писал(а):Еще хотел спросить по поводу функции
int sol_GetLemmaW( HLEM hEngine, const wchar_t * Word, wchar_t * Result, int BufSize )

А зачем тебе UNICODE-ная версия, если ANSI-шная работает? Чисто для интереса?
strateg писал(а):Private Declare Function GetLemmaW Lib "lemmatizator.dll" Alias "sol_GetLemmaW" (ByVal hEngine As Long, ByVal Word As String, ByVal Result As String, ByVal BufSize As Long) As Long

Здесь на форуме преобразования строк обсуждались, есть поиск. Коротко, для интересу, тип String в Бэйсике при передаче его во внешние процедуры подвергается преобразованию в ANSI текущей кодовой страницы точно так же, как это делает StrConv(s, vbFromUnicode). ***

Есть способ избежать такого преобразования, если заменить параметр на фиктивный Long и передавать адреса. Это чревато ошибками при написании и передаче. Оно тебе нужно? В то время как уже есть рабочий и простой код для сопровождения. Есть накладные расходы на преобразование туда-сюда. Вот если последние будут критичны для приложения, тогда имеет смысл перейти на W версии функций.

Есть ещё один ход. Он есть если у тебя есть доступ к MIDL.EXE или MKTYPLIB.EXE. Тогда можно было бы написать IDL файл функций этой библиотеки, подключать её через References и Бэйсик будут правильно передавать параметры.

Ну и напоследок код преобразования A в W:
Код: Выделить всё
Private Declare Function GetLemmaW Lib "lemmatizator.dll" Alias "sol_GetLemmaW" (ByVal hEngine As Long, ByVal Word As String, ByVal Result As String, ByVal BufSize As Long) As Long

  resalt = String(128, " ")
  rez1 = GetLemmaW(rezlem, StrConv("простыни", vbUnicode), resalt, 64) ' ******
  resalt = StrConv(resalt, vbFromUnicode)
  resalt = Left(resalt, InStr(resalt, vbNullChar) - 1)


Код: Выделить всё
Private Declare Function GetLemmaW Lib "lemmatizator.dll" Alias "sol_GetLemmaW" (ByVal hEngine As Long, ByVal Word As Long, ByVal Result As Long, ByVal BufSize As Long) As Long

  resalt = String(128, " ")
  rez1 = GetLemmaW(rezlem, StrPtr("простыни"), StrPtr(resalt), 128)
  resalt = Left(resalt, InStr(resalt, vbNullChar) - 1)


PS
***
При приёме строк обратно происходит преобразование обратно так, как делает StrConv(s, vbUnicode). Поэтому при вызове функций системы, даже когда со строками ничего не происходит и не должно происходить, всё равно происходит их двойная конвертация туда и сюда.

******
Было ошибочно 128! Нужно учесть, что будет в два раза меньше. Либо выделить в два раза больше в resalt = String(128*2, " ").
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 15.10.2010 (Пт) 9:48

Извиняюсь, я ступил, написал vbFromUnicode вместо vbUnicode. Спасибо за подробный ответ.

Вот так всё работает
rez1 = GetLemmaW(rezlem, StrConv("простыни", vbUnicode), resalt, 25)


Юникод мне понадобился потому что есть некоторые другие функции, которые работают только с Юникодом. Теперь этот вопрос решился.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 15.10.2010 (Пт) 10:01

Если Вас не затруднит, возможно Вы поможете еще с одной функцией

есть такая функция
int sol_GetStrings( HGREN_STR hStr, wchar_t** Res )


Res - это вектор. Каждый элемент этого вектора - буфер для размещения строки.

Как здесь указать типы данных? Я сделал так:
(ByVal HGREN_STR As Long, ByVal massiv1 As String) или надо Byref


Потом пытаюсь вызвать

Dim massiv1(20) As String
rez15 = GetStrings(rez12 - указетель на массив, massiv1(0))


Ничего не выходит.

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 15.10.2010 (Пт) 11:19

strateg писал(а):есть такая функция
int sol_GetStrings( HGREN_STR hStr, wchar_t** Res )

Как здесь указать типы данных? Я сделал так:
(ByVal HGREN_STR As Long, ByVal massiv1 As String) или надо Byref

Ты имеешь в виду
Морфологический анализатор писал(а):int sol_CountStrings( HGREN_STR hStr )
Число найденных форм (то есть число элементов в векторе строк). Это число используется для выделения памяти перед вызовом функции sol_GetStrings.

int sol_GetStrings( HGREN_STR hStr, wchar_t** Res )
Вектор Res должен иметь размер, возвращаемый процедурой sol_CountStrings. Каждый элемент этого вектора - буфер для размещения строки длиной не менее, чем возвращается процедурой sol_MaxLexemLen.

Поскольку функция получает Юникодные строки, то из-за вышеупомянутого преобразования в ANSI нужно или заменять на Long или передавать как массив ANSI-шных строк с соответствующими преобразованиями. Но я боюсь, что это будет не просто. Нужно поискать на форуме, где-то были решения, с этим связанные. Я навскидку не напишу.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

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

Re: Подключение сторонней библиотеки на С++

Сообщение Хакер » 15.10.2010 (Пт) 11:41

Чтобы избавиться от преобразования, нужно объявить функции в TLB.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 15.10.2010 (Пт) 15:34

Говорят про tlb хоршо написано в книге Visual Basic 4 "Крепкий
орешек" Б. Мак-Кинни. Но у меня этой книги нет, а в инете ничего путного не нашел.

Да Vi, я имел ввиду именно эти функции.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 15.10.2010 (Пт) 16:30

Почитал я на форуме много копий поломано с этой tlb и безрезультатно, похоже чайники так ничего и не поняли. Я тоже чайник, тем не менее надежда есть.

tlb или в отдельном файле или в секции рессурсов библиотеки. Отдельного файла нет. Секции рессурсов в библиотеки тоже нет. Файла .bas тоже нет.

Может быть такое? И можно ли что-то сделать не имея исходного tlb?

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 15.10.2010 (Пт) 17:18

Vi Опишу как я понимаю ситуацию.
Функция отрабатывает, ищет леммы или другую информацию. Помещает их в некую область памяти. Возвращает указатель. По этому указателю мы находим. С помощью функции sol_CountStrings и указателя мы находим количество возвращенных частей.

Потом нужна функция GetStrings. Она не работает. Но что мешает поличить данную информацию напрямую из памяти. Указатель ведь есть и он указывает на эту область памяти.
Взять байты преобразовать в текст и всё. Или я чего-то недопонимаю в этом процессе?

Даже есть исходник похоже этой функции и если я правильно понимаю он просто тупо копирует из памяти в массив

DLL_ENTRY int sol_GetStrings( HGREN_STR h, wchar_t **Res )
{
if( h==NULL || Res==NULL )
return -1;

for( Container::size_type i=0; i<h->list.size(); i++ )
wcscpy( Res[i], h->list[i].c_str() );

return 0;
}

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 15.10.2010 (Пт) 19:48

strateg писал(а):Потом нужна функция GetStrings. Она не работает. Но что мешает получить данную информацию напрямую из памяти. Указатель ведь есть и он указывает на эту область памяти. Взять байты преобразовать в текст и всё. Или я чего-то недопонимаю в этом процессе?

Нужно проверить, т.к. ДЛЛ у меня нет. Да Бэйсика тоже. Так что, может упасть, сохраняйся.
Код: Выделить всё
Private Declare Function CountStrings Lib "xxx.dll" Alias "sol_CountStrings"(ByVal hStr As Long) As Long
Private Declare Function GetStringsW Lib "xxx.dll" Alias "sol_GetStrings"(ByVal hStr As Long, ByVal vectorStringsW As Long) As Long

Public Declare Function GetMem4 Lib "msvbvm60" (ByVal pSrc As Long, ByVal pDst As Long) As Long

Public Function StrArrPtr(arr() As String, Optional ByVal IgnoreMe As Long = 0) As Long
  GetMem4 VarPtr(IgnoreMe) - 4, VarPtr(StrArrPtr)
End Function

Dim massiv1() As String, addressSAFEARRRAY As Long, addressBSTRPTR As Long
Redim massiv1(CountStrings(hStr)-1)
For i=LBound(massiv1) to UBound(massiv1)
  massiv1(i) = String(sol_MaxLexemLen(), vbNullChar) ' выделили на каждую строку место
Next

addressSAFEARRRAY = StrArrPtr(massiv1)                  '  получили адрес массива
GetMem4 addressSAFEARRRAY + 12, VarPtr(addressBSTRPTR)  '  получили адрес адресов строк

rez1 = GetStringsW(hStr, addressBSTRPTR)

For i=LBound(massiv1) to UBound(massiv1)
  massiv1(i) = Left(massiv1(i), InStr(massiv1(i), vbNullChar) - 1)
Next
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 16.10.2010 (Сб) 19:15

Vi могу дать библиотеки в личку, если надо, они вообщем любопытные.

Программа падает на этих строках

GetMem4 addressSAFEARRRAY + 12, VarPtr(addressBSTRPTR) ' получили адрес адресов строк
rez1 = GetStrings(rez12, addressBSTRPTR)


в addressBSTRPTR 0 ноль, поэтому на фукнции GetStrings падает, так как думаю, ноль в качестве адреса след строки её не устраивает.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 17.10.2010 (Вс) 13:27

Я прочитал в инете что функция StrArrPtr дает указатель на указатель на структуру Safearray

Поэтому добавил еще одну строку
GetMem4 addressSAFEARRRAY, VarPtr(address2)
потом
rez1 = GetStrings(rez12, address2)

Теперь действиельно передается указетль на данные, но функция всё равно падает.
Почему это может быть?

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 18.10.2010 (Пн) 9:09

strateg писал(а):Я прочитал в инете что функция StrArrPtr дает указатель на указатель на структуру Safearray

Поэтому добавил еще одну строку
GetMem4 addressSAFEARRRAY, VarPtr(address2)
потом
rez1 = GetStrings(rez12, address2)

Теперь действительно передается указатель на данные, но функция всё равно падает.
Почему это может быть?

Нужно передавать не адрес массива, а адрес того, что он содержит. Я не работал с StrArrPtr, только знал, что она есть, а проверить сразу не мог. Ну вот попробуй такой код:
Код: Выделить всё
addressSAFEARRRAY = StrArrPtr(massiv1)                  '  получили адрес адреса массива
GetMem4 addressSAFEARRRAY, VarPtr(addressSAFEARRRAY)    '  получили адрес массива
GetMem4 addressSAFEARRRAY + 12, VarPtr(addressBSTRPTR)  '  получили адрес адресов строк

rez1 = GetStringsW(hStr, addressBSTRPTR)
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 18.10.2010 (Пн) 13:32

Да как раз так я и сделал, немного неверно написал, потом конечно передал указатель на данные, к сожалению этот вариант не проходит.

Может быть попытаться взять данные по указателю, который возвращает функция Getlemmas? Этот указтель указывает на список, который существует в памяти.

Сейчас попытаюсь разобраться со структурой этих списков.

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 18.10.2010 (Пн) 14:09

strateg писал(а):Да как раз так я и сделал, немного неверно написал, потом конечно передал указатель на данные, к сожалению этот вариант не проходит.
Может быть попытаться взять данные по указателю, который возвращает функция Getlemmas? Этот указатель указывает на список, который существует в памяти.
Сейчас попытаюсь разобраться со структурой этих списков.

Код: Выделить всё
extern "C" __declspec(dllexport) void __stdcall PassArrayStringW(LPWSTR *pText)
{
   return;
}

У меня эта функция прекрасно приняла данные из VB6:
Код: Выделить всё
Private Declare Function PassArrayStringW Lib ".\moddll.dll" Alias "_PassArrayStringW@4" (ByVal s As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (ByVal ptrToLongSrc As Long, ByVal ptrToLongDest As Long) As Long
Public Function StrArrPtr(arr() As String, Optional ByVal IgnoreMe As Long = 0) As Long
  GetMem4 VarPtr(IgnoreMe) - 4, VarPtr(StrArrPtr)
End Function
...
Dim ss() As String
    ReDim ss(2)
    ss(0) = "english"
    ss(1) = "русский
Dim addressSAFEARRRAY As Long, addressBSTRPTR As Long

GetMem4 StrArrPtr(ss), VarPtr(addressSAFEARRRAY)
GetMem4 addressSAFEARRRAY + 12, VarPtr(addressBSTRPTR)

PassArrayStringW addressBSTRPTR

Может, дело в другом - мало памяти выделяешь в каждом элементе массива или ещё что?
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 18.10.2010 (Пн) 14:14

strateg писал(а):Может быть попытаться взять данные по указателю, который возвращает функция Getlemmas? Этот указтель указывает на список, который существует в памяти.

Вроде с GetLemmas должна работать GetLemmaString, нет?
Код: Выделить всё
' sol_LoadLemmatizatorA sol_LoadLemmatizatorW sol_LoadLemmatizator8
Private Declare Function LoadLemmatizator Lib "lemmatizator.dll" Alias "sol_LoadLemmatizatorA" (ByVal dbName As String) As Long
Private Declare Function LoadLemmatizatorW Lib "lemmatizator.dll" Alias "sol_LoadLemmatizatorW" (ByVal dbNameW As Long) As Long
' sol_DeleteLemmatizator
Private Declare Sub DeleteLemmatizator Lib "lemmatizator.dll" Alias "sol_DeleteLemmatizator" (ByVal hEngine As Long)

' sol_GetLemmaA sol_GetLemmaW sol_GetLemma8
Private Declare Function GetLemma Lib "lemmatizator.dll" Alias "sol_GetLemmaA" (ByVal hEngine As Long, ByVal Word As String, ByVal Result As String, ByVal BufSize As Long) As Long
Private Declare Function GetLemmaW Lib "lemmatizator.dll" Alias "sol_GetLemmaW" (ByVal hEngine As Long, ByVal WordW As Long, ByVal ResultW As Long, ByVal BufSize As Long) As Long

' sol_GetLemmasA sol_GetLemmasW sol_GetLemmas8
Private Declare Function GetLemmas Lib "lemmatizator.dll" Alias "sol_GetLemmasA" (ByVal hEngine As Long, ByVal Word As String) As Long
Private Declare Function GetLemmasW Lib "lemmatizator.dll" Alias "sol_GetLemmasW" (ByVal hEngine As Long, ByVal WordW As Long) As Long
' sol_CountLemmas
Private Declare Function CountLemmas Lib "lemmatizator.dll" Alias "sol_CountLemmas" (ByVal hList As Long) As Long
' sol_GetLemmaStringA sol_GetLemmaStringW sol_GetLemmaString8
Private Declare Function GetLemmaString Lib "lemmatizator.dll" Alias "sol_GetLemmaStringA" (ByVal hList As Long, ByVal iIndex As Long, ByVal Result As String, ByVal BufSize As Long) As Long
Private Declare Function GetLemmaStringW Lib "lemmatizator.dll" Alias "sol_GetLemmaStringW" (ByVal hList As Long, ByVal iIndex As Long, ByVal ResultW As Long, ByVal BufSize As Long) As Long
' sol_DeleteLemmas
Private Declare Sub DeleteLemmas Lib "lemmatizator.dll" Alias "sol_DeleteLemmas" (ByVal hList As Long)

Private Sub Form_Load()
  Dim hEngine As Long, hList As Long, ansiVersion As Boolean
  Dim resalt As String, rez1 As Long, s As String, i As Long
  Dim s1 As String, s2 As String, b1() As Byte, b2() As Byte
 
  ansiVersion = True
  Stop
 
  If ansiVersion Then
    hEngine = LoadLemmatizator("lemmatizer.db")
  Else
    hEngine = LoadLemmatizatorW(StrPtr("lemmatizer.db"))
  End If
'  Debug.Print Hex(hEngine)
 
  s = "простыни"
'  s = "роем"
 
  'Эта функция возвращает в буфер количество лем - 3 и первую найденную
  resalt = String(128, vbNullChar)
  If ansiVersion Then
    rez1 = GetLemma(hEngine, s, resalt, Len(resalt))
  Else
    rez1 = GetLemmaW(hEngine, StrPtr(s), StrPtr(resalt), Len(resalt))
  End If
  resalt = Left(resalt, InStr(resalt, vbNullChar) - 1)
  Debug.Print rez1, Len(s), s, Len(resalt), resalt

  'Эта функция должна вернуть дескриптор списка, но ничего не возвращает
  hList = GetLemmas(hEngine, s)
    rez1 = CountLemmas(hList)
    Debug.Print rez1, Len(s), s
    For i = 0 To CountLemmas(hList) - 1
      resalt = String(128, vbNullChar)
      If ansiVersion Then
        rez1 = GetLemmaString(hList, i, resalt, Len(resalt))
      Else
        rez1 = GetLemmaStringW(hList, i, StrPtr(resalt), Len(resalt))
      End If
      resalt = Left(resalt, InStr(resalt, vbNullChar) - 1)
      Debug.Print rez1, Len(s), s, Len(resalt), resalt
    Next
  Call DeleteLemmas(hList)
 
  Call DeleteLemmatizator(hEngine)

  Unload Me
End Sub
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 18.10.2010 (Пн) 15:47

Ну я попробовал функцию Tokenize и с ней долна быть функция GetStrings.

Хорошо, я еще попробую с GetLemmaString.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 18.10.2010 (Пн) 17:16

GetLemmaString работает.

Вроде всё верно


rezgr = CreateGrammarEngineA("Dic\dictionary.xml")
reztok = Tokenize(rezgr, StrConv("Кошка пьет молоко", vbUnicode), 1)
Dim massiv1() As String
Dim addressSAFEARRRAY As Long
Dim addressBSTRPTR As Long
ReDim massiv1(CountStrings(reztok) - 1)
proverk1 = MaxLexemLen(rezgr) - максимальная 29
For i = LBound(massiv1) To UBound(massiv1)
massiv1(i) = String(MaxLexemLen(rezgr), vbNullChar) ' выделили на каждую строку место
Next

addressSAFEARRRAY = StrArrPtr(massiv1)
GetMem4 addressSAFEARRRAY, VarPtr(addressSAFEARRRAY)
GetMem4 addressSAFEARRRAY + 12, VarPtr(addressBSTRPTR)
rez1 = GetStrings(reztok, addressBSTRPTR)


А по поводу PassArrayStringW я не понял - это наверное не для меня? Какая-то собственная функция?

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 18.10.2010 (Пн) 17:23

strateg писал(а):А по поводу PassArrayStringW я не понял - это наверное не для меня? Какая-то собственная функция?

Это моя функция для отладки, LPWSTR *pText == wchar_t **Res. Так вот при отладке pText[0] == "english", pText[1] == "русский", pText[2] = NULL.

PS
Посмотри правильность определения функции GetStrings - должно быть похоже на определение функции PassArrayStringW.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 18.10.2010 (Пн) 17:54

Теперь работает, спасибо. Тут у меня еще кое-что не ладилось, но я попытаюсь справится сам, в свете новых знаний. Может быть и осилю.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 18.10.2010 (Пн) 18:30

Такая штука значит

Dim rez As Long
rez = SeekWord(rezgr, StrConv("КОРОВА", vbUnicode), 1)
Dim Result2 As String
Result2 = Space(100)
xxxp = StrConv(rez, vbUnicode)
rez2 = GetEntryName(rezgr, xxxp, Result2)
Result3 = StrConv(Result2, vbFromUnicode)


Первая функция получает индек словарной статьи по её имени
Вторая функция должна сделать обратное получить имя словарной статьи по её индексу.

Индекс приходится конвертировать в Unicode, потому что иначе ничего не возвращается. Но если переконвертировать в Unicode? то вместо слова Корова возвращается слово Ящик.

Возможно тут надо как-то по-другому конвертировать число, которое представляет индекс?

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

Re: Подключение сторонней библиотеки на С++

Сообщение Vi » 18.10.2010 (Пн) 22:13

strateg писал(а):Такая штука значит
...
Индекс приходится конвертировать в Unicode, потому что иначе ничего не возвращается. Но если переконвертировать в Unicode? то вместо слова Корова возвращается слово Ящик.

Возможно тут надо как-то по-другому конвертировать число, которое представляет индекс?

Индекс, как правило, не преобразуется - это целое число. Нужно ещё писать то, как ты преобразуешь декларацию функции. Если она будет неправильной, то результата не будет.
' int sol_SeekWord( HGREN hEngine, const wchar_t *Word, bool AllowDynforms )
' int sol_GetEntryName( HGREN hEngine, int EntryIndex, wchar_t* Result )
Код: Выделить всё
Private Declare Function SeekWordW Lib "xxx.dll" Alias "sol_SeekWord" (ByVal hEngine As Long, ByVal WordW As Long, ByVal AllowDynforms As Long) As Long
Private Declare Function GetEntryNameW Lib "xxx.dll" Alias "sol_GetEntryName" (ByVal hEngine As Long, ByVal EntryIndex As Long, ByVal ResultW As Long) As Long
...
Dim Result2 As String
Result2 = Space(100)
rez = SeekWordW(rezgr, StrPtr("КОРОВА"), 1)
if rez >= 0 Then rez2 = GetEntryNameW(rezgr, rez, StrPtr(Result2))

Может быть, маловат размер буфера.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 18.10.2010 (Пн) 22:27

Теперь ясно, теперь работает. вы передали указатель на слово корова, тогда как я передавал Юникод, и поэтому возвращался неверный индекс.

strateg
Новичок
Новичок
 
Сообщения: 31
Зарегистрирован: 12.10.2010 (Вт) 15:06

Re: Подключение сторонней библиотеки на С++

Сообщение strateg » 19.10.2010 (Вт) 10:04

Еще одна функция

HGREN_RESPACK sol_MorphologyAnalysis( HFAIND hEngine, const wchar_t *Sentence, bool Allow_Dynforms, bool Allow_Unknown, int TimeoutMilliSec, int LanguageId )

Private Declare Function MorphologyAnalysis Lib "solarix_grammar_engine.dll" Alias "sol_MorphologyAnalysis" (ByVal hBuilder As Long, ByVal Sentense As Long, ByVal Allow_Dynforms As Integer, ByVal Allow_Unknown As Integer, ByVal TimeoutMilliSec As Long, ByVal Lang As Integer) As Long
Private Declare Function CountGrafs Lib "solarix_grammar_engine.dll" Alias "sol_CountGrafs" (ByVal hBuilder As Long) As Long
Private Declare Function CountRoots Lib "solarix_grammar_engine.dll" Alias "sol_CountRoots" (ByVal hBuilder As Long, ByVal nomergraf As Integer) As Long
Private Declare Function GetRoot Lib "solarix_grammar_engine.dll" Alias "sol_GetRoot" (ByVal hBuilder As Long, ByVal nomergraf As Integer, ByVal nomerroot As Integer) As Long
Private Declare Function GetNodeIEntry Lib "solarix_grammar_engine.dll" Alias "sol_GetNodeIEntry" (ByVal hBuilder As Long, ByVal Hroot As Long) As Long

rez = MorphologyAnalysis(rezgr, StrPtr("пила лежит на столе"), 0, 0, 100, 1)
rez2 = CountGrafs(rez) - получаем одну гарфу
rez3 = CountRoots(rez, 1) - сколько узлов в в 1-й графе
rez4 = GetRoot(rez17, 1, 1) - дескриптор узла
rez5 = GetNodeIEntry(rezgr, rez4) - должен вернуть индекс статьи


В итоге если вызвать функцию MorphologyAnalysis один раз, то в rez3 пятизначное число, если вызвать повторно, то там цифра 2, тогда как должно быть 3. 3 Узла.

Явно что-то идет не так. А у Вас работает эта функция?
В первом параметре GetNodeIEntry вероятно должен передаваться указатель на поисковую машину sol_CreateSearchEngine, а не на граматическую, но всё равно непонятно почему в rez3 такая пляска с цифрами. И в декларации всё верно и указатель на строку передал.

След.

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

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

Сейчас этот форум просматривают: AhrefsBot и гости: 137

    TopList