请求思路,一个DELPHI程序要调用DLL,而DLL中的函数名,参数个数,参数类型为不定,要调用的DLL中的函数名、参数个数、参数类型要可以在窗口中Edit中动

有够难<br>
 
[red]以上的各位,我用过一个流程开发工具,调用的DLL就是普通的DLL,而并不是所谓的<br>array of const 之类的,因为这些被调用的DLL是我自己写的<br>请看截图 http://www.wansoft.com.cn/aaa.jpg &nbsp;[/red]
 
再实现一个封装版的DLL,<br>其中,调用某个公开的函数,可以获得所有的函数列表,<br>函数有一个指针列表,传入字符串数组,再有一个参数表示传入的参数的个数,<br>此DLL进行转化,并调用实际的DLL
 
SQLServer中实现extenal stored procedure 用的就是类似的技术,<br><br>就连Rundll32 所调用的dll也必须编写特殊的接口函数,才能被rundll32调用<br>rundll32 是不能掉用普通的DLL的
 
我说的没错吧? MSDN 上是这样说的:<br>它将命令行参数,直接传递给了某个函数,<br>能被Rundll32调用的函数的形式必须是<br>void CALLBACK EntryPoint(<br>&nbsp; HWND hwnd, &nbsp; &nbsp; &nbsp; &nbsp;// handle to owner window<br>&nbsp; HINSTANCE hinst, &nbsp;// instance handle for the DLL<br>&nbsp; LPTSTR lpCmdLine, // string the DLL will parse<br>&nbsp; int nCmdShow &nbsp; &nbsp; &nbsp;// show state<br>);<br><br><br>Platform SDK: SDK Tools <br><br>Rundll32<br><br>The Run DLL utility (Rundll32.exe) included in Windows enables you to call functions exported from a 32-bit DLL. These functions must have the following syntax:<br><br><br>void CALLBACK EntryPoint(<br>&nbsp; HWND hwnd, &nbsp; &nbsp; &nbsp; &nbsp;// handle to owner window<br>&nbsp; HINSTANCE hinst, &nbsp;// instance handle for the DLL<br>&nbsp; LPTSTR lpCmdLine, // string the DLL will parse<br>&nbsp; int nCmdShow &nbsp; &nbsp; &nbsp;// show state<br>);<br>Note that EntryPoint is a placeholder for the actual function name. For a list of possible show states, see WinMain.<br><br>The following is the command-line syntax for Rundll32:<br><br>rundll32 DllName,FunctionName [Arguments]<br><br>DllName <br>Specifies the name of the DLL. The name cannot contain spaces, commas, or quotation marks. The utility searches for the DLL using the search criteria documented for the LoadLibrary function. Therefore, it is best to use the short name and provide a full path for the DLL. <br>FunctionName <br>Specifies the name of the function to call in DllName. Requires a comma (without no spaces) between DllName and FunctionName. <br>Arguments <br>Optional arguments for FunctionName. <br>Rundll32 loads the specified DLL using LoadLibrary, obtains the address of the function using the GetProcAddress function, and calls the function with the specified arguments, if any. When the function returns, Rundll32 unloads the DLL and exits.<br><br>It is possible to create a Unicode version of the function. Rundll32 first tries to find a function namedEntryPointW. If it cannot find this function, it tries EntryPointA, then EntryPoint. To create a DLL that supports ANSI on Windows Me/98/95 and Unicode otherwise, export two functions: EntryPointW and EntryPoint.<br><br>
 
所以,楼主的要求是很难实现的,<br>如果能实现的话,就只有一种方法,<br>那就是,动态的构造调用堆栈,<br>而且还很危险,参数传递错误,就会Crash<br><br>你输入的参数也无法确定它的类型<br><br>最好是模拟Rundll32 ,如果要调用普通的DLL,那么需要对这些DLL进行二次封装<br>将函数参数类型全都封装成上面所说的形式<br><br>相关链接<br>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tools/tools/rundll32.asp<br><br>http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q164/7/87.asp&amp;NoWebContent=1<br><br>http://support.microsoft.com/default.aspx?scid=kb;EN-US;135068
 
可以根据输入的参数类型,<br>用汇编语言来将参数压入堆栈,然后再调用,<br>必须保证你输入的参数和实际的DLL需要的严格一致
 
TO LICH,谢谢你的回答,<br>不知你看过 http://www.wansoft.com.cn/aaa.jpg &nbsp;没有?<br>这是一个广州恒讯达公司CALL CENTER交换机的流程生成器中调用用户自定义函数的<br>一个截图,流程生成器中共有8种变量类型byte,long,small,string(即pchar),<br>boolean,struct(结构), Dynamic Memory(既内存流)<br>我试着写了个DLL,一个函数,定义了30个参数,各种变量类型都杂乱无序地用到了,<br>如果事先在程序中TYPE好或重截的话,你算算应该type多少行语句?<br>流程生成器生成的是一些代码,我分析过无非是一些数据,并未生成其他动态库,然后一个<br>SERVER程序运行时调用这些代码,实实在在是实现了这个功能,而且容错能力还不错,调用<br>失败不会导致程序崩溃<br>
 
实际上,在Delphi中使用代码块异常保护功能,<br>调用出错并不会有太大的影响,但是错误可能会导致系统崩溃<br><br>我想了一种方法,我先试一下,行的话,我贴出代码:
 
我已经实现了一种方法,例子程序在这里:<br>http://www1.51-51.com/pub/args2.rar<br><br>支持三种数据类型<br>S,I,D<br>表达式样例:<br><br>运行外部程序----<br>kernel32.dll::WinExec S:notepad.exe I:1<br>显示消息框-----<br>user32.dll::MessageBoxA I:0 S:"Hello hahaha" S:"TT01 ok" I:64<br><br>大家看看,提点意见
 
目前只能处理输入的参数,<br>也只支持 stdcall 的调用
 
例子中的返回值,不对
 
我觉得可以实现,因为我们用delphi通过webservice调用EJB时实现了类似的功能;主要思路如下:<br>在DLL中定义一个公共接口函数,带上两个参数:一个是要调用的过程名,另一个是被调用的过程的参数数组,如<br>procedure iMethod(procName: String; vars Array of String);<br>begin<br>&nbsp; //将所有可能调用的过程进行枚举,当然vars[]中的数据类型在这里要进行转换<br>&nbsp; if procName = 'Add' then<br>&nbsp; &nbsp; &nbsp;Add(Vars[0],vars[1]...) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//相应的处理过程需另外编写<br>&nbsp; else if procName = 'Max' then<br>&nbsp; &nbsp; &nbsp;Max(Vars[0],vars[1]...) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//相应的处理过程需另外编写<br>&nbsp; ......<br>end; <br><br>在每次更改了DLL中的方法、或新增加了方法,只需在iMethod中再添加一个else if ****就行
 
返回值的问题已经修正,<br>同时增加了几个调用的示例:<br><br>--启动记事本<br>kernel32.dll::WinExec S:notepad.exe I:1<br>--显示消息框,并获得返回值<br>user32.dll::MessageBoxA I:0 S:"Hello hahaha" S:"TT01 ok" I:67<br>--查找当前程序窗口的句柄<br>user32.dll::FindWindowA I:0 S:Form1<br>--赋值本程序到C盘根目录下,如果存在,则覆盖,强制成功,返回1表示成功<br>kernel32.dll::CopyFileA S:./Project1.exe S:C:/test.exe I:0<br><br>当然,你自己可以调用更多的API函数,或者自己DLL中的函数<br><br>例子程序到这里下载:<br>http://www1.51-51.com/pub/args2.rar<br><br>
 
现在也支持传递变参了,<br>即按地址传递,并可获取传回的字符串参数和整型参数,<br>譬如: 对API函数 GetComputerName 的调用
 
Lich,太谢谢你了,能不能把代码发给我?再次感谢 :)<br>4719373@163.com
 
这里贴出关键部分的代码:<br><br>type<br>&nbsp; TArg = record<br>&nbsp; &nbsp; ArgType: Integer;<br>&nbsp; &nbsp; S: String;<br>&nbsp; &nbsp; I: Integer;<br>&nbsp; &nbsp; D: Double;<br>&nbsp; end;<br><br>&nbsp; TWords = array of String;<br><br>&nbsp; TFunInfo = record<br>&nbsp; &nbsp; DllName: String;<br>&nbsp; &nbsp; FunName: String;<br>&nbsp; &nbsp; Params: array of TArg;<br>&nbsp; &nbsp; Ret: Integer;<br>&nbsp; end;<br><br><br><br>..................<br>function ParseArg(S: String): TArg;<br>var<br>&nbsp; m: Integer;<br>&nbsp; t1, t2: String;<br>&nbsp; c: Char;<br>begin<br>&nbsp; Result.ArgType := 0;<br>&nbsp; Result.S := '';<br>&nbsp; Result.I := 0;<br>&nbsp; Result.D := 0.0;<br>&nbsp; m := Pos(':', S);<br>&nbsp; if m &gt; 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; t1 := UpperCase(Copy(S, 1, m - 1));<br>&nbsp; &nbsp; t2 := Copy(S, m + 1, Length(S));<br>&nbsp; end;<br>&nbsp; if Length(t1) = 1 then<br>&nbsp; begin<br>&nbsp; &nbsp; c := t1[1];<br>&nbsp; &nbsp; case c of<br>&nbsp; &nbsp; &nbsp; 'S': &nbsp;//String<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Result.ArgType := 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; Result.S := UnQuoteString(Trim(t2));<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; 'I': &nbsp;//Integer<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Result.ArgType := 2;<br>&nbsp; &nbsp; &nbsp; &nbsp; Result.I := StrToIntDef(t2, 0);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; 'D', 'F': &nbsp;//Double<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Result.ArgType := 3;<br>&nbsp; &nbsp; &nbsp; &nbsp; Result.D := StrToFloatDef(t2, 0.0);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; end<br>&nbsp; else<br>&nbsp; begin<br>&nbsp; &nbsp; if (t1 = 'INT') or (t1 = 'INTEGER') then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result.ArgType := 1;<br>&nbsp; &nbsp; &nbsp; Result.S := UnQuoteString(Trim(t2));<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else if (t1 = 'STR') or (t1 = 'STRING') then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result.ArgType := 2;<br>&nbsp; &nbsp; &nbsp; Result.I := StrToIntDef(t2, 0);<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else if (t1 = 'FLOAT') or (t1 = 'DOUBLE') then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result.ArgType := 3;<br>&nbsp; &nbsp; &nbsp; Result.D := StrToFloatDef(t2, 0.0);<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else if (t1 = 'VI') or (t1 = 'VINTEGER') then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result.ArgType := 12;<br>&nbsp; &nbsp; &nbsp; Result.I := StrToIntDef(t2, 0);<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br>function ParseFun(S: String): TFunInfo;<br>var<br>&nbsp; m: Integer;<br>&nbsp; v: TWords;<br>&nbsp; i: Integer;<br>begin<br>&nbsp; Result.DllName := '';<br>&nbsp; Result.FunName := '';<br>&nbsp; Result.Ret := 0;<br>&nbsp; v := SplitWithSpace(S, '"');<br>&nbsp; if Length(v) &gt; 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; m := Pos('::', v[0]);<br>&nbsp; &nbsp; if m &gt; 0 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result.DllName := Copy(v[0], 1, m - 1);<br>&nbsp; &nbsp; &nbsp; Result.DllName := UnQuoteString(Result.DllName);<br>&nbsp; &nbsp; &nbsp; Result.FunName := Copy(v[0], m + 2, Length(v[0]));<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; if Result.DllName &lt;&gt; '' then<br>&nbsp; begin<br>&nbsp; &nbsp; SetLength(Result.Params, Length(v) - 1);<br>&nbsp; &nbsp; for i := 1 to Length(v) - 1 do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Result.Params[i - 1] := ParseArg(v);<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br>function RunDllFun(var fun: TFunInfo): Integer;<br>var<br>&nbsp; i, r, t: Integer;<br>&nbsp; d: Double;<br>&nbsp; pd: PIntegerArray;<br>&nbsp; t1, t2: Integer;<br>&nbsp; dll: Integer;<br>&nbsp; f: Pointer;<br>&nbsp; p: PChar;<br>begin<br>&nbsp; Result := 0;<br>&nbsp; dll := LoadLibrary(PChar(fun.DllName));<br>&nbsp; try //finally<br>&nbsp; &nbsp; try //except<br>&nbsp; &nbsp; &nbsp; if dll &lt;&gt; 0 then &nbsp;//load ok<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; f := GetProcAddress(dll, PChar(fun.FunName));<br>&nbsp; &nbsp; &nbsp; &nbsp; if Assigned(f) then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i := Length(fun.Params) - 1 downto 0 do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case fun.Params.ArgType of<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push 0<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetLength(fun.Params.S, 500);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p := PChar(fun.Params.S);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push p<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t := fun.Params.I;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push t<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d := fun.Params.D;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pd := @d;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1 := pd[0];<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t2 := pd[1];<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push t2<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push t1<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 12: //整数变参<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t := Integer(@(fun.Params.I));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push t<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // call the function<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; asm<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; call f;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mov r, eax<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fun.Ret := r;<br>&nbsp; &nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result := -3;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Result := -4;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; Result := -2;<br>&nbsp; &nbsp; end;<br>&nbsp; finally<br>&nbsp; &nbsp; if dll &lt;&gt; 0 then FreeLibrary(dll);<br>&nbsp; end;<br>end;<br><br>function RunDLL2(S: String; var Fun: TFunInfo): Integer;<br>begin<br>&nbsp; Result := -1;<br>&nbsp; Fun := ParseFun(S);<br>&nbsp; if Fun.DllName &lt;&gt; '' then<br>&nbsp; begin<br>&nbsp; &nbsp; try<br>&nbsp; &nbsp; &nbsp; Result := RunDllFun(Fun);<br>&nbsp; &nbsp; except<br>&nbsp; &nbsp; &nbsp; ShowMessage('发生了调用异常');<br>&nbsp; &nbsp; end;<br>&nbsp; end<br>&nbsp; else<br>&nbsp; &nbsp; raise Exception.Create('解析失败,可能是格式不正确');<br><br>end;<br><br><br>.........................................<br>procedure TForm1.Button2Click(Sender: TObject);<br>var<br>&nbsp; s: String;<br>&nbsp; i, r: Integer;<br>&nbsp; t: String;<br>&nbsp; FunInfo: TFunInfo;<br>&nbsp; function GetPaStr(pa: TArg): String;<br>&nbsp; begin<br>&nbsp; &nbsp; case pa.ArgType of<br>&nbsp; &nbsp; &nbsp; 0: &nbsp;Result := 'Null:0';<br>&nbsp; &nbsp; &nbsp; 1: &nbsp;Result := 'S:' + PChar(pa.S);<br>&nbsp; &nbsp; &nbsp; 2: &nbsp;Result := 'I:' + IntToStr(pa.I);<br>&nbsp; &nbsp; &nbsp; 3: &nbsp;Result := 'D:' + FloatToStr(pa.D);<br>&nbsp; &nbsp; &nbsp; 12: Result := 'VI:' + IntToStr(pa.I);<br>&nbsp; &nbsp; &nbsp; else Result := 'UnKnown';<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>begin<br>&nbsp; //表达式调用<br>&nbsp; s := Edit1.Text;<br>&nbsp; if Trim(s) &lt;&gt; '' then<br>&nbsp; begin<br>&nbsp; &nbsp; r := RunDLL2(s, FunInfo);<br>&nbsp; &nbsp; if r = 0 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; for i := 0 to Length(FunInfo.Params) - 1 do<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if i = 0 then t := GetPaStr(FunInfo.Params)<br>&nbsp; &nbsp; &nbsp; &nbsp; else t := t + #13#10 + GetPaStr(FunInfo.Params);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; ShowMessage('调用成功,返回值:' + IntToStr(FunInfo.Ret) + #13#10 +<br>&nbsp; &nbsp; &nbsp; &nbsp; '参数列表:' + #13#10 + t);<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; ShowMessage('调用失败,错误代码:'+ IntToStr(r));<br>&nbsp; end<br>&nbsp; else<br>&nbsp; &nbsp; ShowMessage('请输入函数名称及参数');<br>end;<br>
 
Lich,太谢谢你了,能不能把 <br>UnQuoteString &nbsp;SplitWithSpace 函数的代码也贴出来?谢谢<br>能不能加我一下? QQ:4719373<br>[red]还有一个问题就是:<br>如 function abcd(a1:string;var a2:string):integer; stdcall;<br>你的这个例子好象还不能取得 a2 的返回值啊[/red]
 
动态链接库中不要使用String类型,来做参数,<br>有很多跟共享内存有关的问题,而且其它的语言无法正常调用,<br>所以,建议沿用Windows API的接口方式,采用PChar<br>或者指针类型
 
to lich ,<br>SplitWithSpace 函数我已写好了,UnQuoteString &nbsp;是作什么用的呢?
 
顶部