powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как мне написать API-ф-цию чтоб возвращала строку.
25 сообщений из 53, страница 1 из 3
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315299
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Внутри C++ кода есть.
Код: plaintext
1.
char*	UserName = NULL;



В какой-то момент ей присваивается реальная строка:
Код: plaintext
1.
UserName = NewUserName; //char* NewUserName  



Эту строку UserName надо отфутболить через API в VB6 приложение

Пытаюсь так например:
Код: plaintext
1.
2.
3.
4.
5.
int __stdcall CPP_Get_Registration_Information(char * MyUserName)
{ 
  MyUserName = UserName;
  return 0;
}


Вот как это правильно сделать?

Доставать пытаюсь так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
Private Declare Function CPP_Get_Registration_Information Lib "MyTestDll.dll" _
 (ByVal NewUserName As String) As Long
Private Sub CommandGetRegistrationInformation_Click()
  Dim NewUserName As String
  NewUserName = String$(255, 0)
  CPP_Get_Registration_Information NewUserName
  MsgBox NewUserName
End Sub


Не получается строку прочитать, пусто!

По хорошему на стороне VB конструкция должна быть примерно такая:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
Declare Function CPP_Get_Registration_Information Lib "MyTestDll.dll" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Function GetRegName() As String
Dim RegName As String
    ' Receive a Registration Info from API's CPP_Get_Registration_Information  function
     RegName = String$(255, 0)
     GetRegName = Left(RegName, CPP_Get_Registration_Information(RegName, InStr(RegName, Chr(0)) - 1))
End Function



Но я не понимаю как зарядить эту конструкцию на стороне C++.
C аналогичными ф-циями где надо вернуть несколько чисел (а не строку) я разобрался.
Например:

C++
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
int		TrialDaysTotal		= -1,
		TrialDaysLeft		= -1;
...
	TrialDaysTotal = Total;
	TrialDaysLeft  = Left;
...
extern "C" {
int __stdcall CPP_Get_Trial_Days(int * Total, int * Left)
{ 
  * Total = TrialDaysTotal;
  * Left = TrialDaysLeft;
  return 0;
}



VB6
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Private Declare Function CPP_Get_Trial_Days Lib "MyTestDll.dll" _
 (ByRef Total As Long, ByRef Left As Long) As Long

Private Sub CommandGetTrialDays_Click()
  Dim Total As Long
  Dim Left As Long
  
  CPP_Get_Trial_Days Total, Left
  
  MsgBox "Total=" & Total & " Left=" & Left
End Sub


С int/Long все работает.

Помогите мне char * из C++ вытащить.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315304
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все оказалось немного проще:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
//C++
extern "C" {

char * __stdcall CPP_Get_Registration_Information()
{ 
  return UserName;
}
...



Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
'VB6
Private Declare Function CPP_Get_Registration_Information Lib "MyTestDll.dll"  () As Long

Private Sub CommandGetRegistrationInformation_Click()
  MsgBox PtrToString(CPP_Get_Registration_Information)
End Sub

Function PtrToString(Ptr As Long) As String
    Dim Data As Byte
    Dim str As String
    Dim i As Long
    str = ""
    If Ptr <> 0 Then
        For i = 0 To 10000 '255
            CopyMemory Data, ByVal Ptr + i, 1
            If Data = 0 Then Exit For 'конец строки \0
            str = str & Chr(Data)
        Next i
    End If
    PtrToString = str
End Function


К счастью на VB6 я собаку с доставанием строки по Ptr-указателю давно съел.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315312
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

а просто вернуть BSTR (размещённый через SysAllocString) ?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315338
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

Я рад что у меня хоть как то получилось.

А чем char * плох?
Asprotect в своих API использует именно char *, его я и возвращаю через мою API.
А VB6 по любому получит Long - указатель (Ptr) на начало строки.
А конец строки - нулевой символ.

Проблема возникла из того, что в VB6 нельзя напрямую вызвать нормальные API AsProtect.
Вот здесь чуть подробнее:
Вопрос по API ф-циям AsProtect если кто сталкивался или умеет использовать "сложные" API.

Зато dll-ки с API писать научился.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315398
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А чем char * плох?
кто память освобождать будет?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315427
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

а ты ссылку смотрел постом выше, где более менее полный код приведен?
Конструкция

Код: plaintext
1.
2.
3.
4.
5.
6.
char*	UserName			= NULL;

void __declspec(dllexport) __stdcall GetRegistrationInformation(char* NewUserName){

	UserName = NewUserName;
}



навязана из документации AsProtect.
(верхняя "API" не моя и она сработает автоматом, моя (вызываемая по требованию из VB6) только нижняя)

А AsProtect фиг знает чего там делает и чего освобождает.
Или считаешь, что я должен что-то освобождать со стороны VB, я же только отдаю ссылку на память, а значение там и так лежит с момента как сработает dll (LoadLibrary?)
И полагаю что то что там создается при выгрузке dll (проги) очищается.

Или предлагаешь коверкать типы? Оно стоит? Я и так C++ коды в час по чайной ложке рожаю.
В любом случае UserName запрашивается один раз при старте программы и памяти много не занимает (даже если согласиться что она таки теряется). А почему так уверен что теряется?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315553
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Внутри C++ кода есть.
Код: plaintext
1.
char*	UserName = NULL;


Возможно это будет интересно: в разных C++ компиляторах NULL может иметь разное значение, а не 0, как это можно было бы ожидать, что может привести к неожиданному результату для конструкций вида
Код: plaintext
1.
if(!UserName){...}. 


Поэтому лучше присваивать либо 0, либо nullptr (для C++11).
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315557
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumВозможно это будет интересно: в разных C++ компиляторах NULL может иметь разное значение, а не 0, как это можно было бы ожидать, что может привести к неожиданному результату для конструкций вида
Код: plaintext
1.
if(!UserName){...}

Какие могут быть неожиданности, если оператор отрицания для указателей возвращает отрицание сравнения с NULL?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315570
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77а ты ссылку смотрел постом выше, где более менее полный код приведен?
есть прямой путь
Код: plaintext
1.
2.
3.
4.
5.
extern "C"  BSTR  __declspec(dllexport) __stdcall fnString()
{
	char* retVal = "Самодур";
	return ::SysAllocStringByteLen(retVal,strlen(retVal));	
}
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315574
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovКакие могут быть неожиданности, если оператор отрицания для указателей возвращает отрицание сравнения с NULL?[/quote]
А что тут непонятного? Если символическая константа NULL равна 0, то результат проверки будет 1. В противном случае результат проверки будет 0. Т.о. в зависимости от реализации компилятора результат приведённой мною выше проверки может оказаться различным.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315579
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumА что тут непонятного? Если символическая константа NULL равна 0, то результат проверки будет 1. В противном случае результат проверки будет 0. Т.о. в зависимости от реализации компилятора результат приведённой мною выше проверки может оказаться различным.Ещё раз !указатель == !(указатель == NULL)
Поэтому (если вдруг), найдётся компилятор, где NULL !== 0 - всё будет работать корректно.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315597
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЕщё раз
Код: plaintext
1.
!указатель ==  !(указатель == NULL)


Поэтому (если вдруг), найдётся компилятор, где NULL !== 0 - всё будет работать корректно.
Исходный код:
Код: plaintext
1.
char*	UserName = NULL;


Если записывать в такой форме:
Код: plaintext
1.
if(!(UserName == NULL)){...}


то несомненно, это всегда будет работать правильно, вне зависимости от реализации компилятора.

Но если записать в таком виде:
Код: plaintext
1.
if(!UserName){...}


то возникнет ситуация, о которой я писал выше, поскольку если в реализации конкретного компилятора символическая константа NULL окажется не равной 0, то указанное вами равенство
Код: plaintext
1.
!указатель ==  !(указатель == NULL)


окажется неверным, т.к.
Код: plaintext
1.
!указатель

вернёт 0, в то время как
Код: plaintext
1.
!(указатель == NULL)

вернёт 1.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315603
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compositumвернёт 1.Рассматривайте части моего "равенства" как уравнение и всё встанет на свои места.

P.S. А вы можете привести пример компилятора, где NULL !== 0?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315629
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovРассматривайте части моего "равенства" как уравнение и всё встанет на свои места.
Не вижу, каким образом?
Basil A. SidorovP.S. А вы можете привести пример компилятора, где NULL !== 0?
Я пользуюсь только MS Visual Studio и GNU g++.
А что, обязательно нужно ждать, чтобы споткнуться об это? То, что упоминалось мною выше взято не с потолка, а было вычитано из книжек, где и было дано предупреждение о том, что не стоит слепо полагаться на то, что в C++ всегда NULL == 0, т.к. это не регламентировано в стандарте, но отдано на откуп разработчиков компиляторов.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315642
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вспомнил один из сточников, где читал подобного рода информацию: Стивен Прата, "Язык программирования C++ (C++11). Лекции и упражнения", 6-е издание. Глава 12, стр. 610, примечание "Нулевой указатель в C++11".
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315645
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumТо, что упоминалось мною выше взято не с потолка, а было вычитано из книжекА в этих книжках не пояснялась семантика оператора "boolean not" применительно к указателям?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315651
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovCompositumТо, что упоминалось мною выше взято не с потолка, а было вычитано из книжекА в этих книжках не пояснялась семантика оператора "boolean not" применительно к указателям?
Насколько мне известно, оператор "!" превращает 0 в 1, а любое число, отличное от 0 превращает в 0. Поправьте меня, если я не прав. Я что, где-то выше противоречил этому?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315683
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compositum,

Вы слишком все упрощаете.

Оператор ! (а также if() и т.п.) создает булевый контекст для своего аргумента.
В булевом контекте, число 0 неявно приводится к false, остальные числа к true.
Для указателя другое правило: NULL приводится к false, остальные указатели к true.

Таким образом, какое бы не было физическое значение у нулевых указателей, конструкция !ptr всегда работает корректно.

Теперь про обратную сторону.

Compositum
Код: plaintext
1.
!(указатель == NULL)


вернёт 1.
Это опять упрощение.
Оператор ! не возвращает 0 или 1.
Он возвращает bool, т.е. false или true.
А в числовом контексте (например при присвоении в int), эти значения неявно переводятся в их соответствующие числовые представления, 0 или 1 (насколько я помню стандартом не определено что true это именно 1, но могу ошибаться, т.к. нет времени искать).
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315698
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovskyнасколько я помню стандартом не определено что true это именно 1
быстрый гуглинг показал, что при преобразовании из bool в int по стандарту обязательно приводятся к 0 или 1.
Но это не отменяет все остальное что я говорил.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315724
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyДля указателя другое правило: NULL приводится к false, остальные указатели к true.
Спасибо, учту на будущее. Я думал, что и указатели приводятся к bool на основе числового значения адреса, на который они указывают.
Anatoly Moskovskyнасколько я помню стандартом не определено что true это именно 1, но могу ошибаться, т.к. нет времени искать
любое число, отличное от 0 трактуется как true (из книжек).
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315727
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumЯ думал, что и указатели приводятся к bool на основе числового значения адресаА ведь вам намекали. Долго.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315731
Фотография Compositum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovА ведь вам намекали. Долго.
Мне лучше писать прямо, без намёков, поскольку надлежащего опыта программирования в C++ у меня нет. :)
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38315746
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CompositumAnatoly Moskovskyнасколько я помню стандартом не определено что true это именно 1, но могу ошибаться, т.к. нет времени искать
любое число, отличное от 0 трактуется как true (из книжек).
CompositumМне лучше писать прямо, без намёков
Пишу вам прямо, без намёков - я там в процитированном пишу про перевод из bool в числа. А вы написали про обратное преобразование.
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38317775
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилДмитрий77а ты ссылку смотрел постом выше, где более менее полный код приведен?
есть прямой путь
Код: plaintext
1.
2.
3.
4.
5.
extern "C"  BSTR  __declspec(dllexport) __stdcall fnString()
{
	char* retVal = "Самодур";
	return ::SysAllocStringByteLen(retVal,strlen(retVal));	
}



Хорошо, давай вообще без самодурства.
Есть пример несамодурной API:
GetWindowText function
Код: plaintext
1.
2.
3.
4.
5.
int WINAPI GetWindowText(
  _In_   HWND hWnd,
  _Out_  LPTSTR lpString,
  _In_   int nMaxCount
);


Код для использования GetWindowText из VB6 простой и понятный:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Private Declare Function GetWindowText Lib "user32" Alias _
 "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, _
 ByVal nMaxCount As Long) As Long
...
  Dim buf As String * 256
  Dim Title As String
  Dim length As Long

  ' Get the window's title.
  length = GetWindowText(app_hwnd, buf, Len(buf))
  Title = Left$(buf, length)


Заметь, без использования моей САМОДУРНОЙ PtrToString на стороне VB6. при помощи которой я вытаскиваю String из памяти зная только Ptr.

И я пытаюсь создать свою API по образу и подобию GetWindowText (чтоб возвращала длину и заполняла буфер строчкой).
Делаю так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
char*	UserName			= NULL;
....
  UserName = NewUserName; //короче в char* точно есть строка "1-0-0" из 5 символов не считая \0
...

extern "C" {

int __stdcall LPTSTR_Get_Registration_Information(LPTSTR lpString, int nMaxCount)
{ 
  int lenth = (int) strlen(UserName);
  lpString = (LPTSTR)UserName;
  if (lenth < nMaxCount) {
    lpString[lenth] = 0;
    return lenth;
  }
  else {
    lpString[nMaxCount - 1] = 0;
    return nMaxCount - 1;
  }
}



Достаю так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Private Declare Function LPTSTR_Get_Registration_Information Lib "LicenseDll.dll" _
 (ByVal lpString As String, ByVal nMaxCount As Long) As Long

Private Sub CommandGetReg_Click()
  Dim buf As String * 256
  Dim RegInfo As String
  Dim length As Long
  
  length = LPTSTR_Get_Registration_Information(buf, Len(buf))
  MsgBox length
  RegInfo = Left$(buf, length)
  MsgBox RegInfo
End Sub



MsgBox length -честно возвращает число "5"
А вот
MsgBox RegInfo
ни фига не возвращает (буфер как был пуст, так и остался).

Что я не так написал в dll что у меня буфер строчкой не заполняется?
Как реализовать _Out_ LPTSTR lpString
Я в C-шном коде выделил места подвоха.
Ток вот как правильно я не знаю.
Поможете?
...
Рейтинг: 0 / 0
Как мне написать API-ф-цию чтоб возвращала строку.
    #38317814
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77И я пытаюсь создать свою API по образу и подобию GetWindowText (чтоб возвращала длину и заполняла буфер строчкой).
Делаю так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
char*	UserName			= NULL;
....
  UserName = NewUserName; //короче в char* точно есть строка "1-0-0" из 5 символов не считая \0
...

extern "C" {

int __stdcall LPTSTR_Get_Registration_Information(LPTSTR lpString, int nMaxCount)
{ 
  int lenth = (int) strlen(UserName);
  lpString = (LPTSTR)UserName  Не верно. Нельзя это делать. ;
  if (lenth < nMaxCount) {
    lpString[lenth] = 0;
    return lenth;
  }
  else {
    lpString[nMaxCount - 1] = 0;
    return nMaxCount - 1;
  }
}



Что я не так написал в dll что у меня буфер строчкой не заполняется?
Как реализовать _Out_ LPTSTR lpString
Я в C-шном коде выделил места подвоха.
Ток вот как правильно я не знаю.
Поможете?
Ты не заполняешь буфер, а переопределяешь его.
Строки в С это массивы. Их надо копировать специальными функциями, простому знаку равенства они не подвластны.
Код: plaintext
1.
2.
3.
4.
int __stdcall LPTSTR_Get_Registration_Information(LPTSTR lpString, int nMaxCount)
{ 
  int lenth = (int) strlen(UserName);
  strncpy(lpString, UserName, nMaxCount);
...
Рейтинг: 0 / 0
25 сообщений из 53, страница 1 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как мне написать API-ф-цию чтоб возвращала строку.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]