Tablice dyamiczne w DLL

Odpowiedz Nowy wątek
2011-07-15 14:58
0

Cześć, od razu mówię, że nie chcę używać żadnych Sharememów i innych takich i DLLki mogą być pisane w różnych językach.

Mam taką funkcję:

function foo(var code: integer; var template: PChar): HRESULT; safecall;

Tą funkcję wywołuję z DLL. Jak widać, ma ona zwrócić zmienną code typu integer, a także zmienną template typu PChar. I nie byłoby pytania, gdyby PChar nie był "łańcuchem kończącym się znakiem #0".

Co to dla mnie oznacza? Ano, w tym miejscu dllka musi przekazać pewne dane binarne i np. może to być: 0xFF00AA

W przypadku użycia PChar faktycznie w aplikacji dostanę: 0xFF

Teraz pytanie moje brzmi, jakiego tutaj mogę użyć typu zamiast PChar? Utrudnienie jest takie, że nie znam maksymalnej długości tych danych. Może to być 1 bajt, może 100, a może i 2 kB. I teoretycznie może więcej.

Od początku myślałem o użyciu array of byte co by było najlepszym rozwiązaniem, jednak tutaj musiałbym znać maksymalny jej rozmiar(jak wiadomo, w dll nie przekazujemy tablic dynamicznych). Jakoś ją ograniczyć, a generalnie jedynym tutaj ograniczeniem ma być ilość wolnej pamięci.

Cały czas kombinuję coś ze wskaźnikami, ale tak naprawdę poruszam się na chybił trafił. Ktoś ma może jakiś pomysł?

Pozostało 580 znaków

2011-07-15 15:16
0

czy template jest alokowany przez DLL-kę, czy DLL-ka tylko wypełnia zadany bufor?
gdzie ma być pamięć zwalniana?

Pozostało 580 znaków

2011-07-15 15:33
0
Azarien napisał(a)

czy template jest alokowany przez DLL-kę, czy DLL-ka tylko wypełnia zadany bufor?
gdzie ma być pamięć zwalniana?

Template niestety jest alokowany przez DLLkę.
Zrobiłem taki myk:

  1. Przekazuję wskaźnik na Byte:

    function foo(var pSize: integer; var data: PByte): HRESULT; safecall;
  2. Następnie w dll alokuję pamięć i wypełniam danymi:

    var
    s: string;
    begin
    s:='Test';
    pSize:=length(s);
     
    GetMem(Data, pSize);
    copyMemory(Data, @s, pSize);
    result:=S_OK;
    end;

a w aplikacji głównej:

var
  s: string;
begin
  setLength(s, pSize);
  copyMemory(@s, data, pSize);
end;

I to wydaje się działać. Pozostaje jedynie kwestia zwolnienia pamięci. Muszę chyba napisać procedurę:

procedure DLLFreeMem(P: Pointer);
begin
  FreeMem(P);
end;

i wywołać ją z aplikacji w DLL. W taki sposób to DLLka zwolni zajętą przez siebie pamięć i powinno być git. Jeśli ktoś widzi jakiś błąd w rozumowaniu lub rozwiązaniu, proszę o cynk ;)

[DOPISANE]
Niestety w rozumowaniu jest błąd. Podczas zwalniania biblioteki dostaję AV, nawet gdy używam DLLFreeMem z typem w parametrze jako PByte. Tak więc problem ze zwolnieniem pamięci zostaje.

edytowany 1x, ostatnio: Juhas, 2011-07-15 15:53

Pozostało 580 znaków

2011-07-15 22:58
0

Sprawdź może coś zamazujesz niepoprawnym kopiowaniem, poprawne kopiowanie:
copyMemory(@s[1], data, pSize);


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2011-07-18 12:44
0
_13th_Dragon napisał(a)

Sprawdź może coś zamazujesz niepoprawnym kopiowaniem, poprawne kopiowanie:
copyMemory(@s[1], data, pSize);

Teraz faktycznie błędu nie ma, ale za to zmienna S ma wartość adresu, w którym są potrzebne dane, a nie te dane.

[DOPISANE]
OK, udało mi się zrobić to w taki sposób:

var
  i, pSize: integer;
  p: Pointer;
  s: string;
  data: PByte;
begin
  //pobieram dane DATA i pSIZE wywołując funkcję z DLL
  //...
//a teraz zaczyna się zabawa
    setLength(s, pSize);
    copyMemory(@i, data, 4);
    p:=Ptr(i);
    copyMemory(@s[1], p, pSize);
    showMessage(s);
end;

To działa tak, jak chcę, tylko, że mam wrażenie, że robię to trochę na około. Jeślil ktoś ma lepszy pomysł, to poproszę :)

edytowany 1x, ostatnio: Juhas, 2011-07-18 14:24

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0