爱的眼睛:求助函数的问题,大伙帮看!不够分再加加加!几贴一起给分!火大!

时间:2021-10-19 19:35:08
问题是这样的(怕说不清楚,写得很长了):

已有系列函数:

function AS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer; Options: Integer;const CommandText: WideString; var Params: OleVariant; var OwnerData: OleVariant): OleVariant; 

在另一个unit里有:

function TF2.QueryByIntf(const sFuncName, sParam : string): string;
var
  aExecFunc, vData : String;
begin
  ...
  aExecFunc := 'TF1.'+sFuncName+'('+sParam +')';
  vData :=      ????????                       //如何才能执行 aExecFunc 这个串所描述的函数
  self.cdsQuery.XMLData := vData;
  ...
end;

使得类似如下调用

aFuncName := 'AS_GetRecords';
aParamStr := 'dspQuery,-1,recNum,??1,sSQLCommand,??2,??3';
QueryByIntf(aFuncName,aParamStr);

1.可以达到执行  TF1.AS_GetRecords(dspQuery,-1,recNum,??1,sSQLCommand,??2,??3);的目的。
2.上面AppServer函数如何调用? 特别调用参数中??1,??2,??3该怎么用?

若两问题解决,本贴,下贴,需要的话再开几贴一起给分!
http://community.csdn.net/Expert/topic/3688/3688486.xml?temp=.5886804

   wany97@163.com

28 个解决方案

#1


ding

#2


up,关注中。。。

#3


up!

#4


函数指针数组或TListString

#5


我也不是很懂, 想先問下:
 你的TF1, TF2 是不是在同一個exe 中, 還是你在做 com, dcom 之類, AS_GetRecords 是一個在反台執行的???

#6


TEffectProc = procedure(Screen, Image: TBitmap; const Rect: TRect;
    Step: Integer; Progress: Integer);

  TEffect = record
    Name: String;
    Proc: TEffectProc;
  end;

procedure Effect001(Screen, Image: TBitmap; const Rect: TRect;
  Step: Integer; Progress: Integer);
begin
...
end

可以定义很多函数调用
PSEffects: array[1..2] of TEffect = ((Name: 'Expand from right';Proc: Effect001));

这样调用
PSEffects[1].Proc(Media, Pic, R, Step, Progress);
当然也可以用Name得到Proc,也可以写个类来代替record或定义更多的信息,代码来自picshow组件,仅供参考.

#7


To:  getit911(Windows转Linux中) 

    谢谢指点,我看了OBJECT PASCAL,里面有你说的函数类型,可是需要在调用端先定义成类再实例化引用的(具体的例子还没试,呵呵),而我这里如果已有的函数的参数个数和类型都可能不一样,那不是几乎要把函数重新全部再写一遍了,呵呵
有没通用的方法呀?

TO:  aiirii(ari-爱的眼睛) 
    我实际的应用过程中有两处想用上这种方法,一处是在同一EXE中的两个UNIT,另一处是在客户端与服务器间的两个EXE中的两个UNIT,两种都有,在方法上这两种有什么区别吗?

TO: zwb666(zwb) ,caiso(十年磨一剑), ygflydream(飞飞) 谢谢帮顶,一定给分!

另外,第2小题,AS_GetRecords这类的函数怎么用呀?

#8


查了以往的贴子,问题2自己解决了!呵呵
剩下问题1了,大伙帮帮忙,

我的意思是想把客户端要调用的函数进行分解,把需要调用的函数名称及参数进行包装,通过一个通用的函数传递到服务器端,在服务器端才调用它。 [ 把客户端函数A分解(函数A的名称,函数A的参数:string)当做形参,传递给服务器端的一个函数B,在函数B中重新合成函数A(即aExecFunc)并执行函数A。 ]
不用通用的函数传递,单在客户端调用函数A我也会,但因为要调用的函数类型不一又非常的多,所以想传给服务器,让它来调用。

#9


高深。。

#10


顶一下

#11


回了。。MK

#12


不明白,,能不能详细说说!!

#13


TO: Erice(白雪公猪) 

我的意思是想把客户端要调用的函数进行分解,把需要调用的函数名称及参数包装成两字符串,再通过一个通用函数传递到服务器端,在服务器端才调用它。 [[[ 把客户端函数A分解(函数A的名称,函数A的参数:string)当做形参,传递给服务器端的一个函数B,在函数B中重新合成函数A,并执行函数A。 ]]]

不用通用的函数传递,单在客户端调用函数A我也会,但因为要调用的函数类型不一又非常的多,所以想传给服务器,让它来调用。

#14


感觉在一个什么“delphi葵花宝典”那资料上看的功能有点儿象,
感觉想完全这样操作要考虑的有点多,多个参数放一起,这样操作挺复杂
是不是还有分解这些数据才行呀。

#15


为什么一定要用把函数名做参数的思路呢?难道就不能上传函数名,通过函数名来判断
执行哪个函数么?

if str=func1 then
result = func1(......)
else str=func2 then
result = func2(......)
.....
另外如果在服务器端可能函数还会不断增多,而不想升级客户和服务端程序的话,不妨
把函数写在dll中来调用,用函数名来识别dll文件,各dll内部结构用相同的。
不知道我的理解是不是理解骗了。

#16


过于专业,初学都关注中

#17


TO:  kuki84() 

你的理解没偏,不过不能采用if的判断,因为如果要进行判断的话,那if可能要套上五六十个啦呵呵,
目前函数已有五六十个之多!
我下午在考虑一个和你类似的想法,就是用CASE,但是它不支持串,只支持有序数列(如数字),
于是想能不能定义个stringList的类型,把每个函数名存一行,在通过判断行数,得到行数,再用case
不知道行不行,弄不出来,高手指点一下.

TO: whbo(王红波(决心找份工作)) 
谢谢提醒,我马上去查一下"delphi葵花宝典"

各位高手出来指点一下呀,兄弟先谢啦!

#18


可以得....
1. 你服務端 用TList保存可能調用到的所有函數指針(意圖很明顯了吧)
  當然 裡面得函數指針都已經被初始化為實際得函數
   再用TStringList之類的保存所有函數的名稱(跟上面TList中的完全一致,這裡暫時不考慮函數重載之類的)
2. 當客戶端發送 'FuncA',那麼就直接 TStringList.IndexOf...直接獲得對應得下標 比如i
那麼 就直接 TList[i](argA,argB..) 因為TList裡面保存得就是函數指針 就直接用就是
3. 當然 解析規則你就自己定了 這樣吧 你可以定義一個結構
type CallRec = record
  FuncName: string;
  Args: array of string; // 只要傳值就可以了 類型不需要傳了 服務端知道
end;

你再看看 我說得是不是你得意思。。

#19


这个实际上就是以前人们讨论过的用MethodAddress实现用函数名调用函数的问题。可以搜索到很多文章的,我大概copy一点过来

#20


不定参数

function MyFunc(Params: Array of const):Variant;

var

I: Integer;

begin

Result := '';

for I := 0 to High(Args) do

with Args[I] do

case VType of

vtInteger: ...

vtBoolean: ...

vtChar: ...

vtExtended: ...

vtString: ...

vtPChar: ...

vtObject: ...

vtClass: ...

vtAnsiString: ...

vtCurrency: ...

vtVariant: ...

vtInt64: ...

end;

end;

调用:

var

afunc:TFUNC;

begin;

afunc := GetFunc('MyFunc');

afunc([1,2.34,'abcde']);

GetFunc根据一个字符串返回一个TFUNC变量(函数指针);

afunc([1,2.34,'abcde']);是用一个整型、一个浮点型和一个字符串型参数去调用。

假设现在调用的是MyFunc:

在循环中:(i := 0 to 2)

i=0:VType=vtInteger,VInteger=1

i=1:VType=vtextended,VExtended^=2.34

i=2:VType=vtAnsiString,string(VAnsiString)='abcde'

详见TVarRec的帮助.

不过这种方法无法得到函数的参数信息,调用者必须保证参数匹配,或所有的函数都要能处理任意个数任意类型 的参数,更好的方法是使用Automation对象,由于内容太多,我就不多讲了,用Delphi编写Automation对象非赏容 易,调用也很容易,因为Delphi内置了对Automation对象的支持,可要按字符串调用反而要自己去做了,你可以看 一下MSDN中IDispatch的帮助.C++Builder由于没有Automation对象的内置支持,所以是用字符串来查找 Automation对象的方法的,反而容易实现你的要求.GetFunc由你自己去写;Args写错了,应该是Params,VType是Params[i]的成员.String可以转化为PChar:PChar(String1);

#21


GetFunc函数的实现,你自己参考Tobject的MethodAddress方法:

class function MethodAddress(const Name: ShortString): Pointer;

#22


TO: whbo(王红波(决心找份工作)) 
    找过了,不是,那个是用形参传递函数类型,而不是函数名这样的一个串类型。

TO: beyondtkl(大龙驹<*百善孝为先*>) 
    你说的正是我原来想的变通之道的方法,我试试。

TO: fjx99(fjx99) 
     谢谢指点,不过还有些地方不大明白怎么用,我再看看。

谢谢各位指点,相关不懂的再请教上面的各位。
其它走过路过的兄弟请继续支招。

#23


你这个是三层中中间层返回数据集的方法吧,但我没看懂你到底想知道什么

#24


看你的函数的意思,好象写的过于集成了,好象还要取回BLOB字段内容一样,不过没关系,你的函数定义其实还真够罗嗦,觉得你的问题应该是多个SQL同时发到中间层,也就是批SQL处理,我这样理解对吗?
你可以使用STRINGLIST或者在字段后面加上#0,进行字段分隔,这样在中间层就好分离了

#25


我只要3分就够1万分了。

#26


楼上的,强~~

升星放分,记得通知偶,

#27


>>你的理解没偏,不过不能采用if的判断,因为如果要进行判断的话,那if可能要套上五六十个啦呵呵,

如果是統一參數類型的, 還簡單 , 如果每個函數的參數個數, 類型不同的, 這樣做, 最後更加麻煩, 容易出錯! 
是可以, 只是得不償失!

#28


哦,这样呀,不过已经弄了,只好等下版再改了,呵呵,谢谢aiirii

getit911,没问题,可以先祝贺啦,呵呵

#1


ding

#2


up,关注中。。。

#3


up!

#4


函数指针数组或TListString

#5


我也不是很懂, 想先問下:
 你的TF1, TF2 是不是在同一個exe 中, 還是你在做 com, dcom 之類, AS_GetRecords 是一個在反台執行的???

#6


TEffectProc = procedure(Screen, Image: TBitmap; const Rect: TRect;
    Step: Integer; Progress: Integer);

  TEffect = record
    Name: String;
    Proc: TEffectProc;
  end;

procedure Effect001(Screen, Image: TBitmap; const Rect: TRect;
  Step: Integer; Progress: Integer);
begin
...
end

可以定义很多函数调用
PSEffects: array[1..2] of TEffect = ((Name: 'Expand from right';Proc: Effect001));

这样调用
PSEffects[1].Proc(Media, Pic, R, Step, Progress);
当然也可以用Name得到Proc,也可以写个类来代替record或定义更多的信息,代码来自picshow组件,仅供参考.

#7


To:  getit911(Windows转Linux中) 

    谢谢指点,我看了OBJECT PASCAL,里面有你说的函数类型,可是需要在调用端先定义成类再实例化引用的(具体的例子还没试,呵呵),而我这里如果已有的函数的参数个数和类型都可能不一样,那不是几乎要把函数重新全部再写一遍了,呵呵
有没通用的方法呀?

TO:  aiirii(ari-爱的眼睛) 
    我实际的应用过程中有两处想用上这种方法,一处是在同一EXE中的两个UNIT,另一处是在客户端与服务器间的两个EXE中的两个UNIT,两种都有,在方法上这两种有什么区别吗?

TO: zwb666(zwb) ,caiso(十年磨一剑), ygflydream(飞飞) 谢谢帮顶,一定给分!

另外,第2小题,AS_GetRecords这类的函数怎么用呀?

#8


查了以往的贴子,问题2自己解决了!呵呵
剩下问题1了,大伙帮帮忙,

我的意思是想把客户端要调用的函数进行分解,把需要调用的函数名称及参数进行包装,通过一个通用的函数传递到服务器端,在服务器端才调用它。 [ 把客户端函数A分解(函数A的名称,函数A的参数:string)当做形参,传递给服务器端的一个函数B,在函数B中重新合成函数A(即aExecFunc)并执行函数A。 ]
不用通用的函数传递,单在客户端调用函数A我也会,但因为要调用的函数类型不一又非常的多,所以想传给服务器,让它来调用。

#9


高深。。

#10


顶一下

#11


回了。。MK

#12


不明白,,能不能详细说说!!

#13


TO: Erice(白雪公猪) 

我的意思是想把客户端要调用的函数进行分解,把需要调用的函数名称及参数包装成两字符串,再通过一个通用函数传递到服务器端,在服务器端才调用它。 [[[ 把客户端函数A分解(函数A的名称,函数A的参数:string)当做形参,传递给服务器端的一个函数B,在函数B中重新合成函数A,并执行函数A。 ]]]

不用通用的函数传递,单在客户端调用函数A我也会,但因为要调用的函数类型不一又非常的多,所以想传给服务器,让它来调用。

#14


感觉在一个什么“delphi葵花宝典”那资料上看的功能有点儿象,
感觉想完全这样操作要考虑的有点多,多个参数放一起,这样操作挺复杂
是不是还有分解这些数据才行呀。

#15


为什么一定要用把函数名做参数的思路呢?难道就不能上传函数名,通过函数名来判断
执行哪个函数么?

if str=func1 then
result = func1(......)
else str=func2 then
result = func2(......)
.....
另外如果在服务器端可能函数还会不断增多,而不想升级客户和服务端程序的话,不妨
把函数写在dll中来调用,用函数名来识别dll文件,各dll内部结构用相同的。
不知道我的理解是不是理解骗了。

#16


过于专业,初学都关注中

#17


TO:  kuki84() 

你的理解没偏,不过不能采用if的判断,因为如果要进行判断的话,那if可能要套上五六十个啦呵呵,
目前函数已有五六十个之多!
我下午在考虑一个和你类似的想法,就是用CASE,但是它不支持串,只支持有序数列(如数字),
于是想能不能定义个stringList的类型,把每个函数名存一行,在通过判断行数,得到行数,再用case
不知道行不行,弄不出来,高手指点一下.

TO: whbo(王红波(决心找份工作)) 
谢谢提醒,我马上去查一下"delphi葵花宝典"

各位高手出来指点一下呀,兄弟先谢啦!

#18


可以得....
1. 你服務端 用TList保存可能調用到的所有函數指針(意圖很明顯了吧)
  當然 裡面得函數指針都已經被初始化為實際得函數
   再用TStringList之類的保存所有函數的名稱(跟上面TList中的完全一致,這裡暫時不考慮函數重載之類的)
2. 當客戶端發送 'FuncA',那麼就直接 TStringList.IndexOf...直接獲得對應得下標 比如i
那麼 就直接 TList[i](argA,argB..) 因為TList裡面保存得就是函數指針 就直接用就是
3. 當然 解析規則你就自己定了 這樣吧 你可以定義一個結構
type CallRec = record
  FuncName: string;
  Args: array of string; // 只要傳值就可以了 類型不需要傳了 服務端知道
end;

你再看看 我說得是不是你得意思。。

#19


这个实际上就是以前人们讨论过的用MethodAddress实现用函数名调用函数的问题。可以搜索到很多文章的,我大概copy一点过来

#20


不定参数

function MyFunc(Params: Array of const):Variant;

var

I: Integer;

begin

Result := '';

for I := 0 to High(Args) do

with Args[I] do

case VType of

vtInteger: ...

vtBoolean: ...

vtChar: ...

vtExtended: ...

vtString: ...

vtPChar: ...

vtObject: ...

vtClass: ...

vtAnsiString: ...

vtCurrency: ...

vtVariant: ...

vtInt64: ...

end;

end;

调用:

var

afunc:TFUNC;

begin;

afunc := GetFunc('MyFunc');

afunc([1,2.34,'abcde']);

GetFunc根据一个字符串返回一个TFUNC变量(函数指针);

afunc([1,2.34,'abcde']);是用一个整型、一个浮点型和一个字符串型参数去调用。

假设现在调用的是MyFunc:

在循环中:(i := 0 to 2)

i=0:VType=vtInteger,VInteger=1

i=1:VType=vtextended,VExtended^=2.34

i=2:VType=vtAnsiString,string(VAnsiString)='abcde'

详见TVarRec的帮助.

不过这种方法无法得到函数的参数信息,调用者必须保证参数匹配,或所有的函数都要能处理任意个数任意类型 的参数,更好的方法是使用Automation对象,由于内容太多,我就不多讲了,用Delphi编写Automation对象非赏容 易,调用也很容易,因为Delphi内置了对Automation对象的支持,可要按字符串调用反而要自己去做了,你可以看 一下MSDN中IDispatch的帮助.C++Builder由于没有Automation对象的内置支持,所以是用字符串来查找 Automation对象的方法的,反而容易实现你的要求.GetFunc由你自己去写;Args写错了,应该是Params,VType是Params[i]的成员.String可以转化为PChar:PChar(String1);

#21


GetFunc函数的实现,你自己参考Tobject的MethodAddress方法:

class function MethodAddress(const Name: ShortString): Pointer;

#22


TO: whbo(王红波(决心找份工作)) 
    找过了,不是,那个是用形参传递函数类型,而不是函数名这样的一个串类型。

TO: beyondtkl(大龙驹<*百善孝为先*>) 
    你说的正是我原来想的变通之道的方法,我试试。

TO: fjx99(fjx99) 
     谢谢指点,不过还有些地方不大明白怎么用,我再看看。

谢谢各位指点,相关不懂的再请教上面的各位。
其它走过路过的兄弟请继续支招。

#23


你这个是三层中中间层返回数据集的方法吧,但我没看懂你到底想知道什么

#24


看你的函数的意思,好象写的过于集成了,好象还要取回BLOB字段内容一样,不过没关系,你的函数定义其实还真够罗嗦,觉得你的问题应该是多个SQL同时发到中间层,也就是批SQL处理,我这样理解对吗?
你可以使用STRINGLIST或者在字段后面加上#0,进行字段分隔,这样在中间层就好分离了

#25


我只要3分就够1万分了。

#26


楼上的,强~~

升星放分,记得通知偶,

#27


>>你的理解没偏,不过不能采用if的判断,因为如果要进行判断的话,那if可能要套上五六十个啦呵呵,

如果是統一參數類型的, 還簡單 , 如果每個函數的參數個數, 類型不同的, 這樣做, 最後更加麻煩, 容易出錯! 
是可以, 只是得不償失!

#28


哦,这样呀,不过已经弄了,只好等下版再改了,呵呵,谢谢aiirii

getit911,没问题,可以先祝贺啦,呵呵