Показать сообщение отдельно
  #39  
Старый 24.10.2012, 19:57
reqyz reqyz вне форума
Начинающий
 
Регистрация: 13.02.2010
Сообщения: 104
Репутация: 10
По умолчанию

Цитата:
Сообщение от Bargest
Что делать? Нормально описать параметры функции, в соответствии с официальными документами. В конкретно этом случае определить тип "указатель на эту структуру".

А где pVar учитывать - надо было внимательнее читать. В pVar нужно сохранять не только номер типа, но и адрес переменной этого типа, которая выделяется динамически. В массив Params класть тоже адрес VAR-овской переменной. А после вызова фунцкии проходить по массиву и выводить параметры в зависимости от типа.

я ничего не понял, поэтому сделал как понял(

Код:
function SetFunction(dll, adress, param: String;out res2:string): LongWord;
type
  TPoint=record
    x:longword;
    y:Pointer;
  end;
var
  hdll: HMODULE;
  LastError: LongWord;
  proc: Pointer;
  Params: array of TPoint;
  _par:array of TPoint;//0 1 2 3
  Strings: array of String;
  PrmCount, StrCount, p: Integer;
  p0, p1, p2: String;
  //param =var integer:const 8;boolean:1;out pchar:reqyz; integer:8; ...//например
begin
  hdll := LoadLibrary(Pointer(dll));
  if hdll = 0 then
  begin
    LastError := GetLastError;
    {RaiseErrorFmt('При загрузке библиотеки "%s" возникла ошибка №%d: "%s"',
      [dll, LastError, SysErrorMessage(LastError)]);}
    exit;
  end;

  try
    proc := GetProcAddress(hdll, Pointer(adress));
    if not Assigned(proc) then
    begin
      //RaiseErrorFmt('В библиотеке "%s" отсутствует процедура "%s"', [dll, adress]);
      exit;
    end;
    PrmCount := 0;
    StrCount := 0;

    while param <> '' do
    begin
      p := Pos(' ', param);
      if p = 0 then
      begin
        //RaiseErrorFmt('Ожидался символ " " в строке "%s"', [param]);
        exit;
      end;
      p0 := Copy(param, 1, p - 1);
      Delete(param, 1, p);

      p := Pos(':', param);
      if p = 0 then
      begin
        //RaiseErrorFmt('Ожидался символ ":" в строке "%s"', [param]);
        exit;
      end;
      p1 := Copy(param, 1, p - 1);
      Delete(param, 1, p);

      p := Pos(';', param);
      if p = 0 then
      begin
        //RaiseErrorFmt('Ожидался символ ";" в строке "%s"', [param]);
        exit;
      end;
      p2 := Copy(param, 1, p - 1);
      Delete(param, 1, p);

      if Length(Params) = PrmCount then
      begin
        SetLength(Params, PrmCount + 10);
        SetLength(_par, PrmCount + 10);
      end;

      if p1 = 'integer' then
        Params[PrmCount].x := StrToInt(p2)
      else
      if p1 = 'boolean' then
        Params[PrmCount].x := StrToInt(p2)
      else
      if p1 = 'pchar' then
      begin // Здесь строки нигде не сохранялись, поэтому указатели на них теряли актуальность
        if Length(Strings) = StrCount then
          SetLength(Strings, StrCount + 10);
        Strings[StrCount] := p2;
        Params[PrmCount].x := longWORD(Strings[StrCount]);
        Inc(StrCount);
      end else
      begin
        //RaiseErrorFmt('Неподдерживаемый тип "%s"', [p1]);

      end;

      _par[PrmCount].y:=addr(Params[PrmCount]);

      if(p0 = 'var')then
        _par[PrmCount].x:=1
      else
      if(p0 = 'const')then
        _par[PrmCount].x:=2
      else
      if(p0 = 'out')then
        _par[PrmCount].x:=3
      else
      if(p0 = '')then
        _par[PrmCount].x:=0
      else
      begin
        //RaiseErrorFmt('Неподдерживаемый тип "%s"', [p0]);
      end;
      param[PrmCount].y:=addr(_par[PrmCount].x);

      Inc(PrmCount);
    end;
//mov        ax,word ptr value
    asm
      PUSH ESI
      PUSH EDI
      MOV  ESI, Params[PrmCount].x//тут теперь не компилит
      MOV  ECX, PrmCount
      NEG  ECX
      LEA  ESP, [ESP + ECX * 4] // Здесь была ошибочная инструкция lea esp, [esp - ecx * 4]
      NEG  ECX
      MOV  EDI, ESP
      CLD
      REP  MOVSD
      MOV  EAX, proc
      CALL EAX
      MOV  Result, EAX // Сохраняем результат работы вызванной функции
      POP  EDI
      POP  ESI
    end;
    res2:='';
    for p:=0 to length(_par)-1 do
      if(_par[p].x=1)or(_par[p].y=3)
        then
          res2:=res2+inttostr(p)+':'+inttostr(Params[p].x)+';';
  finally
    FreeLibrary(hdll);
  end;
end;

где использовать новые параметры я не знаю, и что нужно менять в асеме тоже не знаю, но сейчас там глюк, а уже не понимаю чего делаю
Ответить с цитированием