• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 181
  • Last Modified:

DLL-s, problem

I hope, somebody has a experience with this...

When i create a dll, in wich i export the function, wich returns a string (later i changed it to Pchar), sometimes it returns a value, in wich the last char is missing. I found not the reason of this "phenomena".
Needs it any spetial declaration? Spetial calling convention?
0
pistacer
Asked:
pistacer
1 Solution
 
jan_ytCommented:
You can try shortstring, insted of string inside of your DLL
0
 
pistacerAuthor Commented:
well, but i need to pass from dll the string, thaat is longer than 255 chars ...
0
 
rwilson032697Commented:
Can you show us a sample of the code?

Cheers,
Raymond.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
pistacerAuthor Commented:
Well, it is a dll for novell connecting, Novell ndk, but i asked my neighbour and he has observed that on his dll-s too.

========================================
Here is the project, wich calls the dll:

program t_n_fcs;

uses
  Forms,
  test_n_fcs in 'test_n_fcs.pas' {Form1},
  nower in 'nower.pas';

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

-----------------------------------

unit nower;

interface

function R_GetGroupMembers(GroupName:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_GetGroupMembership(UserName:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
procedure R_AddUserToGroup(UserName,GroupName:Pchar); stdcall;
  stdcall; external 'novll.dll';
function R_GetNameOfContext:Pchar; stdcall;
  stdcall; external 'novll.dll';
procedure R_SetContext_s(conts:Pchar); stdcall;
  stdcall; external 'novll.dll';
function R_GetActualObjs(Objtype:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_AbreviateName(Obj:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_CanonizeName(Obj:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';
function R_FindcontextOf(objname,Objtype:Pchar):Pchar; stdcall;
  stdcall; external 'novll.dll';

implementation

end.

-----------------------------------

unit test_n_fcs;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Button2: TButton;
    Label1: TLabel;
    Button3: TButton;
    Button4: TButton;
    Edit3: TEdit;
    Edit4: TEdit;
    Button5: TButton;
    Button6: TButton;
    Edit5: TEdit;
    Button7: TButton;
    Button8: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  nower;

procedure TForm1.Button1Click(Sender: TObject);
begin
  edit1.Text:= R_GetGroupMembers(pchar(uppercase(edit1.text)));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  edit2.Text:= R_GetGroupMembership(pchar(uppercase(edit2.text)));
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  label1.Caption:= R_GetNameOfContext;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  R_SetContext_s(pchar(uppercase(edit3.text)));
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  edit4.text:= R_GetActualObjs(pchar('Group'));
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
  edit4.text:= R_GetActualObjs(pchar('User'));
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
//  edit5.text:= R_FindcontextOf(edit5.text,'User');
  edit5.text:= R_FindcontextOf(pchar(uppercase('cerna610')),pchar('User'));
end;

procedure TForm1.Button8Click(Sender: TObject);
begin
//  edit5.text:= R_FindcontextOf(edit5.text,'Group');
  edit5.text:= R_FindcontextOf(pchar(uppercase('refpc')),pchar('Group'));
end;

end.

-----------------------------------

object Form1: TForm1
  Left = 266
  Top = 107
  Width = 696
  Height = 480
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 96
    Top = 144
    Width = 36
    Height = 13
    Caption = 'Context'
  end
  object Edit1: TEdit
    Left = 8
    Top = 8
    Width = 673
    Height = 21
    TabOrder = 0
    Text = 'Edit1'
  end
  object Button1: TButton
    Left = 8
    Top = 32
    Width = 161
    Height = 25
    Caption = 'Members of group'
    TabOrder = 1
    OnClick = Button1Click
  end
  object Edit2: TEdit
    Left = 8
    Top = 80
    Width = 673
    Height = 21
    TabOrder = 2
    Text = 'Edit2'
  end
  object Button2: TButton
    Left = 8
    Top = 104
    Width = 169
    Height = 25
    Caption = 'Is member of'
    TabOrder = 3
    OnClick = Button2Click
  end
  object Button3: TButton
    Left = 8
    Top = 144
    Width = 75
    Height = 25
    Caption = 'Context'
    TabOrder = 4
    OnClick = Button3Click
  end
  object Button4: TButton
    Left = 8
    Top = 208
    Width = 75
    Height = 25
    Caption = 'Set context'
    TabOrder = 5
    OnClick = Button4Click
  end
  object Edit3: TEdit
    Left = 8
    Top = 176
    Width = 553
    Height = 21
    TabOrder = 6
    Text = 'Edit3'
  end
  object Edit4: TEdit
    Left = 8
    Top = 240
    Width = 673
    Height = 21
    TabOrder = 7
    Text = 'Edit4'
  end
  object Button5: TButton
    Left = 40
    Top = 272
    Width = 75
    Height = 25
    Caption = 'Groups'
    TabOrder = 8
    OnClick = Button5Click
  end
  object Button6: TButton
    Left = 152
    Top = 272
    Width = 75
    Height = 25
    Caption = 'Users'
    TabOrder = 9
    OnClick = Button6Click
  end
  object Edit5: TEdit
    Left = 16
    Top = 320
    Width = 345
    Height = 21
    TabOrder = 10
    Text = 'Edit5'
  end
  object Button7: TButton
    Left = 32
    Top = 352
    Width = 75
    Height = 25
    Caption = 'Find user'
    TabOrder = 11
    OnClick = Button7Click
  end
  object Button8: TButton
    Left = 144
    Top = 352
    Width = 75
    Height = 25
    Caption = 'Find group'
    TabOrder = 12
    OnClick = Button8Click
  end
end

=====================================

and here the main paart of dll:

library novll;

uses
  redukcia in 'redukcia.pas',
  cal_win3 in '\\PSS_AVS2\DATA\AVS\PROJEKTY\DELPHI\sc_units\Cal_win3.pas',
  net_win3 in '\\PSS_AVS2\DATA\AVS\PROJEKTY\DELPHI\sc_units\Net_win3.pas',
  NWHelper in 'D:\novellibdel\samples\delphilib_sample\AddGroup\NWHelper.pas',
  NWHelper2 in 'D:\novellibdel\samples\delphilib_sample\AddGroup\NWHelper2.pas';

exports
  R_GetGroupMembers index 1 name 'R_GetGroupMembers',
  R_GetGroupMembership index 2 name 'R_GetGroupMembership',
  R_AddUserToGroup index 3 name 'R_AddUserToGroup',
  R_GetNameOfContext index 4 name 'R_GetNameOfContext',
  R_SetContext_s index 5 name 'R_SetContext_s',
  R_GetActualObjs index 6 name 'R_GetActualObjs',
  R_AbreviateName index 7 name 'R_AbreviateName',
  R_CanonizeName index 8 name 'R_CanonizeName',
  R_FindcontextOf index 9 name 'R_FindcontextOf';
end.

-------------------------------------

unit redukcia;

interface

uses
  SysUtils,
  Windows,
  Classes,
  cal_win3,
  net_win3;

function R_GetGroupMembers(GroupName:Pchar):Pchar; stdcall;
function R_GetGroupMembership(UserName:Pchar):Pchar; stdcall;
procedure R_AddUserToGroup(UserName,GroupName:Pchar); stdcall;
function R_GetNameOfContext:Pchar; stdcall;
procedure R_SetContext_s(conts:Pchar); stdcall;
function R_GetActualObjs(Objtype:Pchar):Pchar; stdcall;
function R_AbreviateName(Obj:Pchar):Pchar; stdcall;
function R_CanonizeName(Obj:Pchar):Pchar; stdcall;
function R_FindcontextOf(objname,Objtype:Pchar):Pchar; stdcall;

implementation

uses
  nwhelper,
  nwhelper2;

var
  hc:NWDSContextHandle;

function StrlistToPcahr(sin:tstringlist):pchar;
var
  i:integer;
  resq:string;
begin
  resq:= '';
  for i:= 0 to (sin.count - 1)
  do resq:= resq + '@' + sin[i];
  result:= pchar(resq);
end;

function AbreviateStrlist(sin:tstringlist):tstringlist;
var
  i:integer;
begin
  result:= tstringlist.Create;
  result.Clear;
  for i:= 0 to (sin.count - 1)
  do result.Add(Abreviatename(hc,sin[i]));
end;

function CanonizeStrlist(sin:tstringlist):tstringlist;
var
  i:integer;
begin
  result:= tstringlist.Create;
  result.Clear;
  for i:= 0 to (sin.count - 1)
  do result.Add(Canonizename(hc,sin[i]));
end;

function R_AbreviateName(Obj:Pchar):pchar;
begin
  result:= pchar(AbreviateName(hc,obj));
end;

function R_CanonizeName(Obj:Pchar):pchar;
begin
  result:= pchar(CanonizeName(hc,obj));
end;

procedure R_AddUserToGroup(UserName,GroupName:Pchar);
begin
  AddUserToGroup(hc,UserName,GroupName);
end;

procedure R_SetContext_s(conts:Pchar);
begin
  SetContext_s(hc,conts);
end;

function R_GetNameOfContext:pchar;
begin
  result:= pchar(GetNameOfContext(hc));
end;

function R_GetGroupMembers(GroupName:Pchar):Pchar;
var
  ress,resu:tstringlist;
begin
  try
    ress:= GetGroupMembers(hc,GroupName);
    resu:= AbreviateStrlist(ress);
    result:= StrlistToPcahr(resu);
  except
    result:= pchar('ERROR - bad groupname');
  end;
  ress.Free;
  resu.Free;
end;

function R_GetGroupMembership(UserName:Pchar):pchar;
var
  ress,resu:tstringlist;
begin
  try
    ress:= GetGroupMembership(hc,UserName);
    resu:= AbreviateStrlist(ress);
    result:= StrlistToPcahr(resu);
  except
    result:= pchar('ERROR - bad groupname');
  end;
  ress.Free;
  resu.Free;
end;

function R_GetActualObjs(Objtype:Pchar):Pchar;
var
  ress,resu:tstringlist;
begin
  try
    ress:= GetObjectList(hC, objtype);
    resu:= AbreviateStrlist(ress);
    result:= StrlistToPcahr(resu);
  except
    result:= pchar('ERROR - bad groupname');
  end;
  ress.Free;
  resu.Free;
end;

function ScanContextFor(hcontex:NWDSContextHandle;searched,typeob,contname:string):string;
var
  strle,strlf,strlc:tstringlist;
  i:integer;
  curcon:string;
begin
  result:= '';
  SetContext_s(hcontex,contname);
  strle:= GetObjectList(hcontex, typeob);
  strlf:= AbreviateStrlist(strle);
  if strlf.IndexOf(searched) = -1
  then begin
    strlc:= GetContextsStrList(hContex,false);
    for i:= 0 to (strlc.Count - 1)
    do begin
      if result = ''
      then begin
        curcon:= GetNameOfContext(hcontex);
        if curcon = '[Root]'
        then curcon:= strlc[i]
        else curcon:= strlc[i] + '.' + curcon;
        result:= ScanContextFor(hcontex,searched,typeOb,curcon);
        SetContext_s_upward(hcontex);
      end;
    end;
  end
  else result:= contname;
  strle.Free;
  strlf.Free;
end;

function R_FindcontextOf(objname,Objtype:Pchar):Pchar;
var
  resq,objn,objt:string;
begin
  objn:= R_AbreviateName(objname);
  objt:= objtype;
  resq:= ScanContextFor(hc,objn,Objt,'[Root]');
  if resq = ''
  then resq:= 'ERROR - ' + objtype + ' not found'
  else resq:= objname + '.' + resq;
  result:= pchar(resq);
end;


initialization
  hc:= GetContextHandle;

finalization

end.

------------------------------------

..... the other units are tooo big on a spetial wish i can put it here, but the problem can we observe here.
In function R_FindcontextOf in dll, all is running ok. But when i call it with parameter Objtype = 'Group', as i debugged it, when i come to last line "result:= pchar(resq);" and the value of resq is for example 'GROUP.CONTEXT.ENDOFCONTEXT',
on the form i see 'GROUP.CONTEXT.ENDOFCONTEX'.
0
 
pistacerAuthor Commented:
.. or better i should say, the last char is not ommitted, but changed to an unshowable char ($18,$14, or so ...) and the editbox shows a space insteed of it. Then, when i take the input of that edit box after that i changed it, the unshowed char is attached to my input and thereafter the result is ERROR.
0
 
DrDelphiCommented:
I have seen this same thing happen myself from time to time. I have found that the answer in my case was to allocate the memory for the result of the exported function. For example:

Function FooBar(somestring:pchar):PChar;stdcall;
begin
 getMem(result,2000);
 result:=Copy(Strpas(SomeString),1,1999);
end;
 
 
 
Good luck!!

 
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now