SafeArray kullanımı

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
darkangel
Üye
Mesajlar: 21
Kayıt: 01 Tem 2005 05:19
Konum: Denizli

SafeArray kullanımı

Mesaj gönderen darkangel »

Merhaba,
Üretici firma tarafından verilmiş bir dll'den fonsiyon çağırmak istiyorum.

Kullanmam gereken fonksiyon aşağıdaki gibi,

clscommdriver1.read_memintegers(iaddress:Smallint,ilength:smallint,var iArray:PSafeArray;var byUnitId:Byte)

iaddress kısmı tamam mesela 10 diyelim
ilength de tamam mesela 4 diyelim
iArray:PsafeArray kısmını bir türlü kabul ettiremedim burası için nasıl bir değişken tanımlamalıyım.


var
dizi:array[1..10] of integer;


gibi bir değişken tanımladım


"Types of actual and formal var parameters must be identical" diye bir hata veriyor.


Merak ettiğim bir başka konu SafeArray nedir ve nasıl kullanılır?

Yardımlarınız için şimdiden teşekkürler.
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Mrb; bu Pointer bir tip galiba. Sana bu fonksiyondan gelen bilginin veri yapısı ne durumda bilmiyorum ama uydurduğum bir tipte örnek vereyim.

Kod: Tümünü seç

type
  PDizi=^TDizi;
  TDizi=record
    i,j:Integer;

  end;

procedure TForm1.Button1Click(Sender: TObject);
var P:Pointer; Dizi:TDizi; 
begin
  //func(...p);//<-kullanamadığın fonksiyon parametresine P değişkenini gönder
  Dizi:=PDizi(P)^;
end;
gibi bir şekilde kullanabilirsin. Kolay gelsin.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
darkangel
Üye
Mesajlar: 21
Kayıt: 01 Tem 2005 05:19
Konum: Denizli

Mesaj gönderen darkangel »

dizi:PsafeArray;

diye tanımlayıp uses kısmına Activex ekleyince şu anda sorun vermiyor.

clscommdriver1.Read_Memintegers(1,1,dizi,1);

şeklindeki fonksiyon çalışıyor şimdiki sorunum dizi içinde bulunan değerleri almak yani
integer olarak tanımlanmış x değişkenine dizinin ilk elemanını atmak istiyorum

x:=dizi[0]; fakat bu durumda

"Array Type Required" hatası veriyor.
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Mrb; Activex.pas dosyasını açınca PSafeArray tipinin tanımlandığı satırların:

Kod: Tümünü seç

  PSafeArray = ^TSafeArray;
  {$EXTERNALSYM tagSAFEARRAY}
  tagSAFEARRAY = record
    cDims: Word;
    fFeatures: Word;
    cbElements: Longint;
    cLocks: Longint;
    pvData: Pointer;
    rgsabound: array[0..0] of TSafeArrayBound;
  end;
  TSafeArray = tagSAFEARRAY;
şeklinde olduğunu göreceksin. Buna göre örnek bir kullanım ise:

Kod: Tümünü seç

with dizi^ do begin
  ShowMessage(IntToStr(cDims+fFeatures+cbElements+cLocks));
  //pvData:Pointer;<-?
  ShowMessage(IntToStr(rgsabound[0].cElements+rgsabound[0].lLbound));
  end;
şeklinde olacaktır.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
darkangel
Üye
Mesajlar: 21
Kayıt: 01 Tem 2005 05:19
Konum: Denizli

Mesaj gönderen darkangel »

sabankaraman hocam cevap için teşekkürler. Dizi elemanlarının değerlerini nasıl görürüm mesela,
1. eleman, 2, eleman ......

şimdiden teşekkürler.
Kullanıcı avatarı
darkangel
Üye
Mesajlar: 21
Kayıt: 01 Tem 2005 05:19
Konum: Denizli

Mesaj gönderen darkangel »

sabanakman hocam ismini yanlış yazdığım için kusura bakma. Projeyi bitirmek için oldukça sıkışmış durumdayım.
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Önemli değil, zaten yazdğın pencerenin sağ üst kısmında Edit butonuna basınca yazdıklarını değiştirebiliyorsun. Kullandığın fonksiyonun ürettiği dizinin veri yapısı hakkında hiç bir bilgim olmadığı için çok fazla yardımcı olamayacağım fakat tahminime göre izlemen yolu söyleyeyim.

Kod: Tümünü seç

  PSafeArrayBound = ^TSafeArrayBound;
  tagSAFEARRAYBOUND = record
    cElements: Longint;
    lLbound: Longint;
  end;
  TSafeArrayBound = tagSAFEARRAYBOUND;
  SAFEARRAYBOUND = TSafeArrayBound;

  PSafeArray = ^TSafeArray;
  tagSAFEARRAY = record
    cDims: Word;
    fFeatures: Word;
    cbElements: Longint;
    cLocks: Longint;
    pvData: Pointer;
    rgsabound: array[0..0] of TSafeArrayBound;
  end;
  TSafeArray = tagSAFEARRAY;
  SAFEARRAY = TSafeArray;
Tanımlarına göre tagSAFEARRAY içinde pvData: Pointer; tanımı fonksiyondan dönen asıl bilginin tutulduğu yer gibime geliyor. Buna göre olay ilk verdiğim örneğe yöneliyor. tagSAFEARRAY içinde bulunan bilgiler bu gelen dizi şeklindeki bilgi ile alakalı diğer bilgiler galiba. (Dizinin boyu, özelliği vs.) Fonksiyon diyelimki şöyle kullandın:

Kod: Tümünü seç

type
  PDizi = ^TDizi;
  TDizi = array[0..MaxListSize - 1] of Integer;

procedure TForm1.Button1Click(Sender: TObject);
var Bilgi:PSafeArray; Dizi:PDizi;
  iaddress,ilength:smallint;
  byUnitId:Byte;
begin
  clscommdriver1.read_memintegers(iaddress,ilength,Bilgi,byUnitId);
  with Bilgi^ do begin
    Dizi:=pvData;
    ShowMessage(IntToStr(Dizi^[0]+Dizi^[1]));
  end;
end;
Buradan ben dizi için Integer bir tip kullandım ama fonksiyonun ürettiği veri yapısı nedir bilemem. Ayrıca dizinin özellik, başlangıç ve bitiş değerlerini Bilgi^ değişkeninden elde edebilirsin. Bu bilgileri en iyi bu fonksiyonu yazan firmaya sormak veya bu konuda yayınladıkları kaynaklara başvurmak aksi halde başka şekilde çözemezsin. Belki aynı şeyleri kullanan başka birisi denk gelirde cevap yazarsa o başka :) . Kolay gelsin.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
darkangel
Üye
Mesajlar: 21
Kayıt: 01 Tem 2005 05:19
Konum: Denizli

Mesaj gönderen darkangel »

tekrar merhaba herkese,
yardımlarınız ve biraz araştırmayla çözümü buldum.Aşağıda sizinle paylaşıyorum.

procedure TForm1.Button1Click(Sender: TObject);
var
arraybounds:TsafeArrayBound;
arraydata:pointer;
iMI:psafearray;
plcid:byte;


a:array[0..15] of word;
p:Pointer;
i:integer;
IE:string;

type
integerarray=array of word;
begin
plcid:=1;b:=1;
arraybounds.lLbound:=0;
arraybounds.cElements:=1;
iMI:=SafeArrayCreate(varinteger,0,Arraybounds);
clscommdriver1.Read_MemIntegers(20,16,iMI,plcid);

if SafeArrayAccessData( iMI, ArrayData ) = S_OK then
begin
for i:= 0 to 15 do

begin
a:=integerarray(Arraydata);
showmessage(inttostr(a));
//a[] dizisini bildiğimiz klasik dizi olarak kullanabiliyoruz.

end;
SafeArrayUnAccessData(iMI);
end;
end;


herkese iyi çalışmalar.
Cevapla