动态链接库返回字符串的问题,有程序.

时间:2021-04-27 18:59:28
function GetSysParamEx(ParamKey:PChar):PChar;stdcall;
var
  cnn:TAdoConnection;
  ads:TAdoDataSet;
begin
  cnn:=TADOConnection.Create(Application);
  cnn.ConnectionString:= GetConnectionString;
  cnn.LoginPrompt:=false;
  cnn.Open;
  ads:=TAdoDataSet.Create(Application);
  ads.Connection:=cnn;
  ads.Close;
  ads.CommandText:='select * from SSysParams where ParamKey=''MaxConsumption''';
  ads.Open;
  if ads.RecordCount>0 then
  begin
    result:=PChar(ads.FieldByName('ParamValue').AsString);
  end
  else
    result:='';
  ads.Free;
  cnn.Free;
end;

为什么调用的时候返回值都是为空?

20 个解决方案

#1


ads变量在函数返回后就被释放了,怎么引用???

#2


function GetSysParamEx(ParamKey:PChar):PChar;stdcall;
var
  cnn:TAdoConnection;
  ads:TAdoDataSet;
  p : pchar;
begin
  cnn:=TADOConnection.Create(Application);
  cnn.ConnectionString:= GetConnectionString;
  cnn.LoginPrompt:=false;
  cnn.Open;
  ads:=TAdoDataSet.Create(Application);
  ads.Connection:=cnn;
  ads.Close;
  ads.CommandText:='select * from SSysParams where ParamKey=''MaxConsumption''';
  ads.Open;
  if ads.RecordCount>0 then
  begin
    getmem (p,length (FieldByName('ParamValue').AsString));
    ...//复制到P
    result:=p;
  end
  else
    result:='';
  ads.Free;
  cnn.Free;
end;

#3


你不應該用 result:=PChar(ads.FieldByName('ParamValue').AsString);
而是應該用 StrCopy 之類的復製, 
要不然, 只是將指針簡單的指向 一版內存, 到函數結束, 那片內存(ads.FieldByName('ParamValue').AsString);) 可能已經被釋放了

我一般是這樣的
function GetSysParamEx(ParamKey:PChar; const myResult: pchar):boolean;stdcall;

#4


aiirii(ari-爱的眼睛) 说的对,不能采用直接付值的方法

#5


aiirii(ari-爱的眼睛) 高手就是高手。

// 加一个参数 nResultSize 表示分配给 myResult 的空间大小
function GetSysParamEx(ParamKey:PChar; const myResult: pchar; const nResultSize: Integer):boolean;stdcall;

提示楼主一下:myResult 的空间是在调用 GetSysParamEx 之前分配的,而不是由 GetSysParamEx 分配。——Win32 API 中凡是用了 PChar (LPCSTR) 的,几乎都是遵循这么一个原则。

#6


pchar p;
string s;

//Pchar to string :         
s:=StrPas(p); 

//string to pchar :
getmem(p,length(s));
StrPCopy(p,s);

#7


好!

#8


向高手学习

#9


dickeybird888(小鸟)  说的有点不对吧:
//string to pchar :
getmem(p,length(s));   // 应该是 GetMem(p, Length(s) + 1); ——字符串末尾还有个 #0.
StrPCopy(p,s);

#10


哈哈

#11


不好意思

#12


如果在函数内部给它分配内存,那用完之后怎么释放它?

#13


分配:
GetMem(p, Size);
释放:
FreeMem(p, Size); 或 FreeMem(p);

#14


哈哈,其实是楼主的ads.RecordCount都是等于-1,所以返回值都是空啦 
还用得着操作内存吗,汗,高手就是不同..

楼主用下面这个试试
ads.CursorLocation :=3; 
ads.open;

#15


学习
学习~

#16


向高手学习

#17


最好是在返回前把要返回的值保存起来
然后不管你的连接等怎么释放
值都不会丢失了

#18


就象楼上的说的
把结果先用个变量保存起来
然后不管你的连接怎么释放
都不会影响结果 而导致丢失了

#19


Dll 中返回 String 是很麻烦的
把返回改为 WideString 的,或 Variant 的就可以了
以现在的计算机不会在乎这么点转换速度的

function GetSysParamEx(ParamKey:PChar):WideString;stdcall;
。。。
Reslt := ads.FieldByName('ParamValue').AsString;
若真的要返回 String 要保证 String 在Dll 中不被释放,并且在主程序中不被修改才可以
一般讲来返回 const 值和 dll中的全局变量是可以的,尽量还是用 WideString

#20


GetMem(p, Length(s)+1);  //字符串末尾还有个 #0.
    StrPCopy(p,s);
    result := p;
这样写可以通过,但会不会造成内存泄漏?

#1


ads变量在函数返回后就被释放了,怎么引用???

#2


function GetSysParamEx(ParamKey:PChar):PChar;stdcall;
var
  cnn:TAdoConnection;
  ads:TAdoDataSet;
  p : pchar;
begin
  cnn:=TADOConnection.Create(Application);
  cnn.ConnectionString:= GetConnectionString;
  cnn.LoginPrompt:=false;
  cnn.Open;
  ads:=TAdoDataSet.Create(Application);
  ads.Connection:=cnn;
  ads.Close;
  ads.CommandText:='select * from SSysParams where ParamKey=''MaxConsumption''';
  ads.Open;
  if ads.RecordCount>0 then
  begin
    getmem (p,length (FieldByName('ParamValue').AsString));
    ...//复制到P
    result:=p;
  end
  else
    result:='';
  ads.Free;
  cnn.Free;
end;

#3


你不應該用 result:=PChar(ads.FieldByName('ParamValue').AsString);
而是應該用 StrCopy 之類的復製, 
要不然, 只是將指針簡單的指向 一版內存, 到函數結束, 那片內存(ads.FieldByName('ParamValue').AsString);) 可能已經被釋放了

我一般是這樣的
function GetSysParamEx(ParamKey:PChar; const myResult: pchar):boolean;stdcall;

#4


aiirii(ari-爱的眼睛) 说的对,不能采用直接付值的方法

#5


aiirii(ari-爱的眼睛) 高手就是高手。

// 加一个参数 nResultSize 表示分配给 myResult 的空间大小
function GetSysParamEx(ParamKey:PChar; const myResult: pchar; const nResultSize: Integer):boolean;stdcall;

提示楼主一下:myResult 的空间是在调用 GetSysParamEx 之前分配的,而不是由 GetSysParamEx 分配。——Win32 API 中凡是用了 PChar (LPCSTR) 的,几乎都是遵循这么一个原则。

#6


pchar p;
string s;

//Pchar to string :         
s:=StrPas(p); 

//string to pchar :
getmem(p,length(s));
StrPCopy(p,s);

#7


好!

#8


向高手学习

#9


dickeybird888(小鸟)  说的有点不对吧:
//string to pchar :
getmem(p,length(s));   // 应该是 GetMem(p, Length(s) + 1); ——字符串末尾还有个 #0.
StrPCopy(p,s);

#10


哈哈

#11


不好意思

#12


如果在函数内部给它分配内存,那用完之后怎么释放它?

#13


分配:
GetMem(p, Size);
释放:
FreeMem(p, Size); 或 FreeMem(p);

#14


哈哈,其实是楼主的ads.RecordCount都是等于-1,所以返回值都是空啦 
还用得着操作内存吗,汗,高手就是不同..

楼主用下面这个试试
ads.CursorLocation :=3; 
ads.open;

#15


学习
学习~

#16


向高手学习

#17


最好是在返回前把要返回的值保存起来
然后不管你的连接等怎么释放
值都不会丢失了

#18


就象楼上的说的
把结果先用个变量保存起来
然后不管你的连接怎么释放
都不会影响结果 而导致丢失了

#19


Dll 中返回 String 是很麻烦的
把返回改为 WideString 的,或 Variant 的就可以了
以现在的计算机不会在乎这么点转换速度的

function GetSysParamEx(ParamKey:PChar):WideString;stdcall;
。。。
Reslt := ads.FieldByName('ParamValue').AsString;
若真的要返回 String 要保证 String 在Dll 中不被释放,并且在主程序中不被修改才可以
一般讲来返回 const 值和 dll中的全局变量是可以的,尽量还是用 WideString

#20


GetMem(p, Length(s)+1);  //字符串末尾还有个 #0.
    StrPCopy(p,s);
    result := p;
这样写可以通过,但会不会造成内存泄漏?

#21