![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передача массивов через СОМ. [D7, XP]
Darvin © (2008-07-02 10:29:00)Здравствуйте!
Программа на Delphi должна использовать com сервер, написанный на C#. Все бы ничего, но параметрами методов интерфейса должны быть динамические массивы или любой другой тип для передачи относительно больших объемов данных (несколько килобайт). Взаимодействие с простым типом данных я отработал. В сервере на C# пишу следующее:
private int[] arr1;
public void SetData(object data)
{
arr1 = (int[])data;
}
Как это можно интерпретировать на Delphi?
Я делал следующим образом:
ITestIface1= interface
['{CDE93811-24B5-4920-A543-8790EE403F31}']
procedure Method1 ( out A : Integer ); stdcall;
procedure Method2 ( A : Integer; out B : Integer ); stdcall;
procedure SetData ( Data : OleVariant ); stdcall;
function GetData : OleVariant; stdcall;
end; // of ITestIface
var
FTest1 : ITestIface1;
...
procedure TForm4.FormCreate(Sender: TObject);
begin
try
// Создаем COM-объект и запрашиваем у него интерфейс
FTest1 := CreateComObject(CLASS_Test1Auto) as ITestIface1;
except
on E : EOleSysError do begin
FTest1 := nil;
edData.Text := 'Ошибка';
end;
end;
end;
procedure TForm4.Button1Click(Sender: TObject);
var
Data : OleVariant;
I : Integer;
begin
Data := VarArrayCreate ( [0, 9], varInteger );
Data := FTest1.GetData;
edData.Text := '';
for I:=0 to 9 do
edData.Text := edData.Text + IntToStr ( Data[I] );
end;
При выполнении строчки Data := FTest1.GetData; вылетает ошибка.
DiamondShark (2008-07-02 19:35:00) [1]
> Я делал следующим образом:
>
> ITestIface1= interface
> ['{CDE93811-24B5-4920-A543-8790EE403F31}']
> procedure Method1 ( out A : Integer ); stdcall;
> procedure Method2 ( A : Integer; out B : Integer ); stdcall;
>
> procedure SetData ( Data : OleVariant ); stdcall;
> function GetData : OleVariant; stdcall;
> end; // of ITestIface
Это какой-то неиллюзорный трандец.
либо
function GetData : OleVariant; safecall;
либо
function GetData(out RetVal: OleVariant): HRESULT; stdcall;
> надо попробовать. для простых типов работает stdcall
Вы что, эти слова как заклинания используете, не вникая в смысл?
Сергей М. (2008-07-02 11:45:00) [2]
> Darvin © (02.07.08 10:49) [12]
>
> >Сергей М. ©
> для простых типов работает stdcall
Разберись для начала, в чем принципиальное отличие этих соглашений
Василий Жогарев (2008-07-02 11:35:00) [3]
> Пример работы с SafeArray можешь кинуть?
http://delphimaster.ru/cgi-bin/forum.pl?id=1209549911&n=8&p=1
Darvin (2008-07-02 11:29:00) [4]>tesseract ©
Пример работы с SafeArray можешь кинуть?
tesseract (2008-07-02 11:20:00) [5]
> для передачи произвольных данных подходит тип bstr (он же
> WideString :))
Для передачи массива через COM идеально подходит SafeArray. Который delphi в принципе может как VariantAray трактовать, но я вручную, нужную мне часть переписал.
> А как pointer передать через com? В стандартных типах его
> нет...
Странно по TCP-IP тоже не передаёться. Смотри iStream + CreateStreamOnHGlobal лучше для передачи. Можно просто через глобальную память, но не уверен, что это правильный шаг.
Darvin (2008-07-02 11:16:00) [6]Попробовал создать unit из tlb файла, параметры массивы типа PSafeArray
umbra (2008-07-02 11:03:00) [7]для передачи произвольных данных подходит тип bstr (он же WideString :))
Но распаковку и упаковку данных надо будет проводить вручную.
Darvin (2008-07-02 10:49:00) [8]>Сергей М. ©
надо попробовать. для простых типов работает stdcall
Darvin (2008-07-02 10:49:00) [9]>Ega23 © PChar?
А если внутри нулевые элементы массива?
Сергей М. (2008-07-02 10:48:00) [10]Подозреваю, что соглашение о вызове должно быть safecall
Darvin (2008-07-02 10:48:00) [11]> Василий Жогарев ©
Нет, эта строка проходит нормально. Я писал сервер на Delphi, там без этой строки не работает
Василий Жогарев (2008-07-02 10:45:00) [12]Я так думаю ошибка у тебя получается вот тут
Data := VarArrayCreate ( [0, 9], varInteger );. Хотя могу и ошибаться.
Ega23 (2008-07-02 10:45:00) [13]PChar?
Darvin (2008-07-02 10:43:00) [14]>umbra ©
не пишет. Project1 обнаружена ошибка. Приложенние будет закрыто. При трассировке останавливается, вызывая окно CPU
Darvin (2008-07-02 10:41:00) [15]> Ega23 ©
А как pointer передать через com? В стандартных типах его нет...
umbra (2008-07-02 10:41:00) [16]
> При выполнении строчки Data := FTest1.GetData; вылетает
> ошибка.
какая?
Darvin (2008-07-02 10:38:00) [17]Собственно, вот:
namespace LibraryTest
{
[GuidAttribute("CDE93811-24B5-4920-A543-8790EE403F31")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(true)]
public interface IMyInteface1
{
void Method1(out int a);
void Method2(/*[in]*/ int a, out int b);
void SetData(object data);
object GetData();
}
[Guid("43668C3A-4C10-4381-9959-287FE971E7C9")]
[ClassInterface(ClassInterfaceType.None), ComVisible(true)]
public class Class1 : IMyInteface1
{
private int num = 5;
private int[] arr = {0,1,2,3,4,5,6,7,8,9};
private int[] arr1;
public void Method1(out int a)
{
a = num;
}
public void Method2(/*[in]*/ int a, out int b)
{
b = a * a;
}
public void SetData(object data)
{
arr1 = (int[])data;
}
public object GetData()
{
return arr;
}
}
}
Василий Жогарев (2008-07-02 10:35:00) [18]
> private int[] arr1;
> public void SetData(object data)
> {
> arr1 = (int[])data;
> }
Покажи полный скелет интерфейса написанный на C#.
Ega23 (2008-07-02 10:33:00) [19]Buffer : Pointer
BuffLength : DWORD
?