Здравствуйте 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
Здравствуйте Аноним, Вы писали:
А>Постой! Но ведь я уже так делал просто со строками. Например так.
А>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.
Можешь так же заменить его на массив вариантов. При этом структуры эмулировать на вариантах же.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте 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 мне нравится больше. Спасибо за подсказку.
Здравствуйте AEgor, Вы писали:
AE>Как проще, а главное правильнее получить массив строк программой на VB из DLL на С++?
VB умеет автоматически конвертировать любой Unicode BSTR в ASCII, перед передачей во внешнюю функцию. Единственная проблема, это то, что VB передает все параметры по ссылке, включая и строки. Так как BSTR указатель на строку, VB передает ее по ссылке, для С это указатель на указатель на строку.
Вот так можно передавать строки:
//код в MyDLL.dllvoid __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", чтобы соглашение имен была сишной, а не С++.
Здравствуйте 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 нравится больше всего...
Спасибо.