Подключение dll (C++) к проекту VB 6.0

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Kverter
Сообщения: 13
Зарегистрирован: 06 ноя 2013, 10:02

Здравствуйте! Проблемма в подключении ДЛЛ к VB 6.
есть библиотека на C++

Код: Выделить всё

//ConsoleApplication2.cpp: определяет точку входа для консольного приложения.
//
//#define _UNICODE
#pragma comment( lib, "Activeds.lib" )
#pragma comment( lib, "Adsiid.lib" )
//#pragma comment( lib , "adsldp.dll" )
//#include <activeds.h>
#include <Iads.h>
#include <Adshlp.h>
#include <winldap.h>
#include <iostream>
#include <atlbase.h>
 #include <windows.h>
   #include <lm.h>
   #include <stdio.h>
#include <Lmcons.h>
#include <string>
#include <atlconv.h>
#include <string.h>
using namespace std;
 
extern "C" __declspec(dllexport) string sAMAccountName ()
{
    HRESULT hr;
    IADsADSystemInfo *pADsys;
BSTR bstr;
CoInitialize(NULL);
 hr = CoCreateInstance(CLSID_ADSystemInfo,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_IADsADSystemInfo,
                             (void**)&pADsys);
 hr = pADsys->get_UserName(&bstr);
    IADs *pUsr=NULL;

 
USES_CONVERSION;
string strDesc = static_cast<CHAR*>(CW2A(bstr));
 
 string LDAP="LDAP://";
 string path = LDAP + strDesc;  
 wstring wstr( path.begin(), path.end() );
// const char *path1 = path.c_str();
 
LPCTSTR path2 = W2CT( wstr.c_str( ) );
 //LPCWSTR path2 = (LPCWSTR)wstr;
hr = ADsGetObject( path2, IID_IADs,(void**)&pUsr);
 
VARIANT var;
VariantInit(&var);
hr = pUsr->Get(CComBSTR("sAMAccountName"), &var );
/*if ( SUCCEEDED(hr) )
{
    printf("sAMAccountName: %S\n", V_BSTR(&var) );
    VariantClear(&var);
} */
//USES_CONVERSION;
 
string s2(W2A(var.bstrVal));
return s2;
}
 
 
extern "C" __declspec(dllexport) VARIANT userPrincipalName ()
{
    HRESULT hr;
    IADsADSystemInfo *pADsys;
BSTR bstr;
CoInitialize(NULL);
 hr = CoCreateInstance(CLSID_ADSystemInfo,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_IADsADSystemInfo,
                             (void**)&pADsys);
 hr = pADsys->get_UserName(&bstr);
    IADs *pUsr=NULL;
 
USES_CONVERSION;
string strDesc = static_cast<CHAR*>(CW2A(bstr));
 
 string LDAP="LDAP://";
 string path = LDAP + strDesc;  
 wstring wstr( path.begin(), path.end() );
// const char *path1 = path.c_str();
 
LPCTSTR path2 = W2CT( wstr.c_str( ) );
 //LPCWSTR path2 = (LPCWSTR)wstr;
hr = ADsGetObject( path2, IID_IADs,(void**)&pUsr);
 
VARIANT userPrincipalName;
VariantInit(&userPrincipalName);
hr = pUsr->Get(CComBSTR("userPrincipalName"), &userPrincipalName );
/*if ( SUCCEEDED(hr) )
{
    printf("userPrincipalName: %S\n", V_BSTR(&userPrincipalName) );
    VariantClear(&userPrincipalName);
} */
return userPrincipalName;
}
extern "C" __declspec(dllexport) VARIANT Group ()
{
    HRESULT hr;
    IADsADSystemInfo *pADsys;
BSTR bstr;
CoInitialize(NULL);
 hr = CoCreateInstance(CLSID_ADSystemInfo,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_IADsADSystemInfo,
                             (void**)&pADsys);
 hr = pADsys->get_UserName(&bstr);
    IADs *pUsr=NULL;
 
USES_CONVERSION;
string strDesc = static_cast<CHAR*>(CW2A(bstr));
 
 string LDAP="LDAP://";
 string path = LDAP + strDesc;  
 wstring wstr( path.begin(), path.end() );
// const char *path1 = path.c_str();
 
LPCTSTR path2 = W2CT( wstr.c_str( ) );
 //LPCWSTR path2 = (LPCWSTR)wstr;
hr = ADsGetObject( path2, IID_IADs,(void**)&pUsr);
 
VARIANT var;
VariantInit(&var);
hr = pUsr->Get(CComBSTR("memberOf"), &var );
return var;
}
extern "C" __declspec(dllexport) void out(VARIANT  var)
{
    HRESULT hr;
    LONG lstart, lend;
    SAFEARRAY *sa = V_ARRAY( &var );
    VARIANT varItem;
 
    // Get the lower and upper bound.
    hr = SafeArrayGetLBound( sa, 1, &lstart );
    hr = SafeArrayGetUBound( sa, 1, &lend );
 
    // Iterate and print the content.
    VariantInit(&varItem);
    printf("Getting service dependencies using IADs :\n");
    for ( long idx=lstart; idx <= lend; idx++ )
    {
        hr = SafeArrayGetElement( sa, &idx, &varItem );
        printf("%S ", V_BSTR(&varItem));
        VariantClear(&varItem);
    }
    printf("\n");
 
    VariantClear(&var);
}

и есть код на vb 6.0

Код: Выделить всё

Private Declare Function sAMAccountName Lib "C:\Users\1\Documents\Visual Studio 2012\Projects\ConsoleApplication18\Debug\ConsoleApplication18.dll" () As Integer
 
Private Sub Command1_Click()
Dim s As String
s = sAMAccountName
End Sub
при запуске просто зависает и все,помогите пожалуйста.
Проблема по ходу в самой библиотеке...
Kverter
Сообщения: 13
Зарегистрирован: 06 ноя 2013, 10:02

В общем понял я в чем проблема. Проблема в типах данных VB нужно чтоб функция из DLL возвращала тип данных hlstr, но в c++ нет такого типа, нашел некий vbapi.h где описан тип,но проблема в том что он не компилица
Ошибка 9 error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию c:\vbapi.h 837
Ошибка 14 error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию c:\vbapi.h 838
Ошибка 18 error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию c:\vbapi.h 839
Ошибка 5 error C2371: VARIANT: переопределение; различные базовые типы c:\vbapi.h 84
Ошибка 3 error C2371: HSZ: переопределение; различные базовые типы c:\vbapi.h 49
Ошибка 1 error C2371: FSHORT: переопределение; различные базовые типы c:\vbapi.h 37
Ошибка 6 error C2371: DRAGINFO: переопределение; различные базовые типы c:\vbapi.h 383
Ошибка 4 error C2371: CURRENCY: переопределение; различные базовые типы c:\vbapi.h 65
Ошибка 2 error C2371: CHAR: переопределение; различные базовые типы c:\vbapi.h 38
Ошибка 12 error C2182: _export: недопустимое использование типа "void" c:\vbapi.h 838
Ошибка 10 error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "VBTERMCC" c:\vbapi.h 838
Ошибка 7 error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "VBINITCC" c:\vbapi.h 837
Ошибка 15 error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "VBGetModelInfo" c:\vbapi.h 839
Ошибка 13 error C2086: BOOL _export: переопределение c:\vbapi.h 838
Ошибка 17 error C2040: _export: "LPMODELINFO" отличается по уровням косвенного обращения от "BOOL" c:\vbapi.h 839
вот такие ошибки, кто посоветует что делать?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Никогда и ни за что VB не поймёт STL-ный тип std::string. Возвращение из функции сложного типа, завязанного на внутренние особенности языка/библиотеки автоматически лишает эту функцию универсальности и сужает её использование рамками языка/библиотеки.

Раз у тебя библиотека внутри использует COM, то почему бы тебе не сделать собственный COM объект, а из VB просто создать его и вызвать его метод? VB отлично работает с COM.

Если не хочешь разбираться с тем, как сделать свой COM объект, то возврати из функции хотя бы BSTR. VB, вроде как, умеет работать с ним.

И ещё замечение не совсем по теме. Используй Release, когда указатели на COM объекты тебе уже не нужны. Я об этом ещё в прошлой твоей теме писал. Сейчас у тебя эта память просто ликает. Это не профессионально.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Kverter
Сообщения: 13
Зарегистрирован: 06 ноя 2013, 10:02

В общем,строка возвращается в проект на VB, но коряво...для ее обработки приходится использовать след.код на VB

Код: Выделить всё

NewStr3 = sAMAccountName()
For i = 1 To k Step 1
If Mid(NewStr3, i, 1) <> vbNullChar Then
Text3.Text = Text3 + Mid(NewStr3, i, 1)
End If
Next i
т.е через символ встречается vbNullChar как это исправить????я думаю проблема может быть в кодировке...
вот функция sAMAccountName() на с++

Код: Выделить всё

extern "C" __declspec(dllexport) BSTR CCONV sAMAccountName ()
{
	HRESULT hr;
	IADsADSystemInfo *pADsys;
BSTR bstr;
CoInitialize(NULL);
 hr = CoCreateInstance(CLSID_ADSystemInfo,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_IADsADSystemInfo,
                             (void**)&pADsys);
 hr = pADsys->get_UserName(&bstr);
	IADs *pUsr=NULL;
USES_CONVERSION;
string strDesc = static_cast<CHAR*>(CW2A(bstr));

 string LDAP="LDAP://";
 string path = LDAP + strDesc;  
 wstring wstr( path.begin(), path.end() );
// const char *path1 = path.c_str();

LPCTSTR path2 = W2CT( wstr.c_str( ) );
 //LPCWSTR path2 = (LPCWSTR)wstr;
hr = ADsGetObject( path2, IID_IADs,(void**)&pUsr);

VARIANT var;
VariantInit(&var);
hr = pUsr->Get(CComBSTR("sAMAccountName"), &var );

return var.bstrVal;
}
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

BSTR в дефайнах студии - это широкая строка, так что ничего удивительного, что там идёт после каждого символа ноль. Я ожидал, что VB-сику можно будет об этом сказать, указав тип возвращаемого значения при декларации функции. Поиграйся с декларацией, возможно получится.

Если не поможет, то сделай возвращаемое значение char*. Тогда придётся сделать статический буфер символов внутри функции, конвернтуть из BSTR в него, и возвратить указатель.

P.S. Да удали ж ты память. Перед выходом из функции сделай:

Код: Выделить всё

pUsr->Release();
VariantClear(var);
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Kverter
Сообщения: 13
Зарегистрирован: 06 ноя 2013, 10:02

Уже решил этот вопрос.....но столкнулся с другой проблемой....при переносе скомпиленого экзешника на VB в другую(чистую) систему, он ругается что не может найти мою написанную dll, хотя путь правильный и она там есть...в чем трабла?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Целиком пусть весь есть? "C:\Users\1\Documents\Visual Studio 2012\Projects\ConsoleApplication18\Debug\ConsoleApplication18.dll"

Вообще хардкодить путь в программе не принято. Убери путь, и оставь только имея dll. Тогда dll будет браться из текущей папки. То есть для запуска нужно будет exe, скомпилированный на VB и dll, скомпилированную в студии, положить в одну папку и всё будет работать, куда бы ты эту папку потом не перенёс.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Kverter
Сообщения: 13
Зарегистрирован: 06 ноя 2013, 10:02

Оно ни так ни так не работает, я думаю может у меня ДЛЛ имеет зависимости, только вот какие не могу понять....
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

В студию входи программа DependencyWalker. Её так же можно стащить в интеренете, как отдельную утилитку. Она позволяет посмотреть все депенденсы исполняемых файлов на Windows. Очень рекомендую. Скорее всего на чистом компютрере не установлены стандартные dll студии, которые линкует наша dll.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Kverter
Сообщения: 13
Зарегистрирован: 06 ноя 2013, 10:02

К сожалению сейчас не могу проверить, но я так уже смотрел, там тянется 5 шт ДЛЛ , но я посмотрел они все на месте в Windows\system32, больше вроде ни каких либ не показало
Ответить