Передача массива строк из C++ в VB
От: AEgor  
Дата: 29.08.02 13:41
Оценка:
Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?
Re: Передача массива строк из C++ в VB
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.08.02 14:15
Оценка: -2
Здравствуйте AEgor, Вы писали:

AE>Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?


Из длл никак. Нужно иметь не просто длл, а COM-сервер. Вот тогда описываешь свою структуру в IDL с указанием гуида (лучше вообще описывать структуру в VB). Далее запихиваешь структуры в SAFEARRAY и передаешь (параметр метода нужно описывать ()в IDL) как SAFEARRAY(struct MyStruct)).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Передача массива строк из C++ в VB
От: Аноним  
Дата: 29.08.02 14:22
Оценка:
Здравствуйте VladD2, Вы писали:

VD>Здравствуйте AEgor, Вы писали:


AE>>Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?


VD>Из длл никак. Нужно иметь не просто длл, а COM-сервер. Вот тогда описываешь свою структуру в IDL с указанием гуида (лучше вообще описывать структуру в VB). Далее запихиваешь структуры в SAFEARRAY и передаешь (параметр метода нужно описывать ()в IDL) как SAFEARRAY(struct MyStruct)).


Постой! Но ведь я уже так делал просто со строками. Например так.

Declare Sub GetLine Lib "name.dll" Alias "CppGetLine" ( ByVal S As String )

Потом вызов:

Private Sub Form_Load()
Dim S As String
Call GetLine S
MsgBox S
End Sub
Re[3]: Передача массива строк из C++ в VB
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.08.02 16:28
Оценка:
Здравствуйте Аноним, Вы писали:

А>Постой! Но ведь я уже так делал просто со строками. Например так.


А>Declare Sub GetLine Lib "name.dll" Alias "CppGetLine" ( ByVal S As String )


А>Потом вызов:


А>Private Sub Form_Load()

А>Dim S As String
А>Call GetLine S
А>MsgBox S
А>End Sub

Дело в том, что структуры в VB — это automation-структуры. По этому работать с ними нужно черз COM. В принципе у VB есть какой-то внутренний механизм работы с неописанными в tlb структурами, но он недокументирован. Единственный надежный способ это SAFEARRAY.

Можешь так же заменить его на массив вариантов. При этом структуры эмулировать на вариантах же.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Передача массива строк из C++ в VB
От: AEgor  
Дата: 30.08.02 05:02
Оценка:
Здравствуйте VladD2, Вы писали:

VD>Здравствуйте Аноним, Вы писали:


А>>Постой! Но ведь я уже так делал просто со строками. Например так.


А>>Declare Sub GetLine Lib "name.dll" Alias "CppGetLine" ( ByVal S As String )


А>>Потом вызов:


А>>Private Sub Form_Load()

А>>Dim S As String
А>>Call GetLine S
А>>MsgBox S
А>>End Sub

VD>Дело в том, что структуры в VB — это automation-структуры. По этому работать с ними нужно черз COM. В принципе у VB есть какой-то внутренний механизм работы с неописанными в tlb структурами, но он недокументирован. Единственный надежный способ это SAFEARRAY.


VD>Можешь так же заменить его на массив вариантов. При этом структуры эмулировать на вариантах же.


Ну можно ещё через CALLBACK-функцию. То есть передать адрес функции на VB которая принимает строку, а в DLL на С++ вызывать эту функцию по числу строк. Но, пожалуй, вариант с SafeArray мне нравится больше. Спасибо за подсказку.
Re: Передача массива строк из C++ в VB
От: Sergey Zhulin  
Дата: 30.08.02 06:54
Оценка:
Здравствуйте AEgor, Вы писали:

AE>Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?


VB умеет автоматически конвертировать любой Unicode BSTR в ASCII, перед передачей во внешнюю функцию. Единственная проблема, это то, что VB передает все параметры по ссылке, включая и строки. Так как BSTR указатель на строку, VB передает ее по ссылке, для С это указатель на указатель на строку.

Вот так можно передавать строки:

//код в MyDLL.dll
void __stdcall DisplayStringByRef(LPCSTR* ppszString)
{
  MessageBox(NULL, *ppszString, "Display String ByRef",
                   MB_OK | MB_ICONINFORMATION);
}

void __stdcall FillString(LPSTR pszString, LONG cSize)
{
  char buffer[] = "Hello from the C DLL!";

  if (cSize > strlen(buffer))
    strcpy(pszString, buffer);
}
//def file для экспорта

      LIBRARY MyDLL
      DESCRIPTION 'DLL for invoking C functions'
      EXPORTS
         DisplayStringByVal
         DisplayStringByRef
         FillString
         InStrRev

//код для VB

      Option Explicit

      Private Declare Sub DisplayStringByVal Lib "MyDLL.dll" _
         (ByVal sMyString As String)
      Private Declare Sub FillString Lib "MyDLL.dll" _
         (ByVal sMyString As String, ByVal cBufferSize As Long)


На самом деле, COM для передачи строк между C++ и VB не нужен. Просто нужно помнить что функции которые хочется вызывать из VB должны декларироваться как extern "C", чтобы соглашение имен была сишной, а не С++.

С уважением, Сергей Жулин
Re: Передача массива строк из C++ в VB
От: Vi2 Удмуртия http://www.adem.ru
Дата: 30.08.02 08:04
Оценка: 10 (1)
Здравствуйте AEgor, Вы писали:

AE>Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?


А мне кажется, что такое определение должно отработать (с правильным соответствием имён GetStringArray в .def-файле)
Declare Function GetStringArray Lib "MyDLL.dll" () As String()

extern "C" SAFEARRAY* __stdcall GetStringArray()
{
    SAFEARRAY* psa = ::SafeArrayCreateVector(VT_BSTR, 0/*LBound*/, 10/*LBound*/);
    // заполнение массива psa через ::SysAllocString как содержащего BSTR-ки
    return psa;
}
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Передача массива строк из C++ в VB
От: AEgor  
Дата: 30.08.02 09:04
Оценка:
Здравствуйте Sergey Zhulin, Вы писали:

SZ>Здравствуйте AEgor, Вы писали:


AE>>Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?


SZ>VB умеет автоматически конвертировать любой Unicode BSTR в ASCII, перед передачей во внешнюю функцию. Единственная проблема, это то, что VB передает все параметры по ссылке, включая и строки. Так как BSTR указатель на строку, VB передает ее по ссылке, для С это указатель на указатель на строку.


SZ>Вот так можно передавать строки:


SZ>
SZ>//код в MyDLL.dll
SZ>void __stdcall DisplayStringByRef(LPCSTR* ppszString)
SZ>{
SZ>  MessageBox(NULL, *ppszString, "Display String ByRef",
SZ>                   MB_OK | MB_ICONINFORMATION);
SZ>}

SZ>void __stdcall FillString(LPSTR pszString, LONG cSize)
SZ>{
SZ>  char buffer[] = "Hello from the C DLL!";

SZ>  if (cSize > strlen(buffer))
SZ>    strcpy(pszString, buffer);
SZ>}
SZ>//def file для экспорта

SZ>      LIBRARY MyDLL
SZ>      DESCRIPTION 'DLL for invoking C functions'
SZ>      EXPORTS
SZ>         DisplayStringByVal
SZ>         DisplayStringByRef
SZ>         FillString
SZ>         InStrRev

SZ>//код для VB

SZ>      Option Explicit

SZ>      Private Declare Sub DisplayStringByVal Lib "MyDLL.dll" _
SZ>         (ByVal sMyString As String)
SZ>      Private Declare Sub FillString Lib "MyDLL.dll" _
SZ>         (ByVal sMyString As String, ByVal cBufferSize As Long)
SZ>


SZ>На самом деле, COM для передачи строк между C++ и VB не нужен. Просто нужно помнить что функции которые хочется вызывать из VB должны декларироваться как extern "C", чтобы соглашение имен была сишной, а не С++.


SZ>С уважением, Сергей Жулин



Признаться, я имел ввиду несколько другое. Как передавать строки я знаю.
Имелся ввиду МАССИВ строк. И судя по ответам, вариант с VARIANT-ом с SafeArray нравится больше всего...
Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.