如果我有一个界面,如:
IPluginAPI = interface
['{590DFF0B-CA00-46CC-84B0-3848103D4C5A}']
function add (a : double; b : double) : double;
function sub (a : double; b : double) : double;
function mult (a : double; b : double) : double;
function divide (a : double; b : double) : double;
end;
Run Code Online (Sandbox Code Playgroud)
无论如何使用RTTI获取GUID的值?我正在使用Delphi XE.
我正在尝试动态调用驻留在函数表中的过程或函数的能力.特定的应用程序是一个DLL,它导出一个指向函数表的指针以及有关参数和类型数量的信息.然后,宿主应用程序能够查询DLL并调用函数.如果它们是对象方法,我可以使用Rtti来调用它们,但它们是正常的过程和函数.DLL必须导出普通函数指针而不是对象,因为DLL可以用任何语言编写,包括C,Delphi等.
例如,我在DLL中声明并填写了一条记录:
TAPI = record
add : function (var a, b : double) : double;
mult : function (var a, b : double) : double;
end;
PAPI = ^TAPI;
Run Code Online (Sandbox Code Playgroud)
我检索指向此记录的指针,声明为:
apiPtr : PAPI;
Run Code Online (Sandbox Code Playgroud)
假设我还可以访问记录中每个条目的过程名称,参数数量和参数类型.
假设我想调用add函数.要添加的函数指针将是:
@apiPtr^.add // I assume this will give me a pointer to the add function
Run Code Online (Sandbox Code Playgroud)
我假设除了使用一些asm来推送堆栈上的必要参数并检索结果之外别无他法.
第一个问题,将程序声明为cdecl的最佳调用约定是什么?在通话之前组装堆栈似乎最简单.
第二个问题,网上是否有任何实际可行的例子?我遇到了http://www.swissdelphicenter.ch/torry/showcode.php?id=1745(DynamicDllCall),它接近我想要的但我简化如下,它现在返回一个指针(EAX)到结果:
function DynamicDllCall(proc : pointer; const Parameters: array of Pointer): pointer;
var x, n: Integer;
p: Pointer;
begin
n := High(Parameters);
if n > -1 then begin …Run Code Online (Sandbox Code Playgroud) 关于软件插件系统的实际操作,我有一个非常基本的问题.我理解一个简单的插件设计是如何工作的,即插件添加到托管应用程序的设计.例如,插件会为绘图程序添加新的过滤器.主机知道它必须调用插件提供的名为filter的方法.在这种情况下,所有插件都是独立的.
我的问题涉及一个插件可以使用另一个插件中的工具的情况.例如,可能有一个插件提供绘制数据的能力,而另一个插件生成数据.如果数据生成器插件之前从未见过图形插件,我认为它无法知道在图形插件中调用哪些方法.我认为在这些情况下,数据生成器插件的开发人员必须能够以抽象类或接口的形式访问图形插件API的描述.这是插件依赖的运作方式,即插件是否明确知道其他插件可能具有的Apis?
我刚刚构建了这样一个插件系统,并且插件能够使用其他插件,我包含在每个插件需要知道的插件接口的源代码副本中.这种方法的问题在于,如果一个新的绘图插件出现但是使用不同的API,则数据生成器插件无法在不首先重新编译的情况下使用它,以便它知道新的API.这对我来说似乎不对.
我知道这似乎是一个非常简单的问题并有一个明显的答案,但我花了几个小时搜索互联网,我没有遇到关于这个问题的明确声明.
我在Delphi语言中遇到过一些我之前没有注意到的东西.考虑一个简单的记录和指向该记录的指针:
TRecord = record
value : double;
end;
PTRecord = ^TRecord;
Run Code Online (Sandbox Code Playgroud)
现在声明一个PTRecord类型的变量:
var x : PTRecord;
Run Code Online (Sandbox Code Playgroud)
并创造一些空间:
x := new (PTRecord);
Run Code Online (Sandbox Code Playgroud)
我注意到我可以使用'.'来访问值字段.符号和'^.' 符号.因此,以下两行似乎在操作上是等效的,编译器不会抱怨并且运行时工作正常:
x.value := 4.5;
x^.value := 2.3;
Run Code Online (Sandbox Code Playgroud)
我原以为'^.' 是正确的,唯一的方式来获取价值?我的问题是,使用更简单的点符号是否可以,或者如果我不使用指针间接'^',我会遇到麻烦吗?也许这是众所周知的行为,但这是我第一次遇到它.
我有一个FireMonkey表单,在表单的OnPaint事件上有以下代码.我期待一个带有径向渐变的球,但我只得到一个红色的球,没有渐变.问题是我做错了什么.在XE3上运行它.如果我将渐变样式更改为gsLinear,我会得到一个线性渐变.我还需要指定其他东西才能显示径向渐变吗?
procedure TForm2.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
var MyRect : TRectF;
begin
MyRect.Create (85, 85, 115, 115);
Canvas.Fill.Gradient.Style := TGradientStyle.gsRadial;
Canvas.Fill.Gradient.Color := claRed;
Canvas.Fill.Gradient.Color1 := claBlue;
Canvas.Fill.Kind := TBrushKind.bkGradient;
Canvas.FillEllipse (MyRect, 100);
end;
Run Code Online (Sandbox Code Playgroud) 我有一个第三方dll,我无法更改并以不规则的间隔将其输出发送到stdout.我想捕获标准输出并将其显示在TMemo控件中.之前的答案(Delphi - 从静态链接的MSVC++编译的DLL捕获stdout和stderr输出)显示了如何将这样的输出捕获到文件,我想将其捕获到TMemo.
可能的解决方案:我可以读取文件,因为它填满了stdout的输出并轮询了文件,但是我需要从先前保存的输出中识别新输出.PLus它似乎不是一个真正的解决方案.我已经做了很多互联网搜索,我发现最常见的相关答案是如何从外部应用程序捕获stdout,这不是我想要做的,我想从dll捕获输出.还有这个代码片段,但我真的不明白它在做什么或如何使用它 - http://embarcadero.newsgroups.archived.at/public.delphi.language.delphi.win32/201010/10101510449. HTML但它似乎解决了同样的问题.有没有人在他们的互联网旅行中发现任何与此主题相关的内容?
我有一些基于Pipes工作的东西,并不像我想象的那么困难,但有一件事让我很烦恼.这是代码:
var
TextBuffer: array[1..32767] of AnsiChar;
TextString: AnsiString;
BytesRead, BytesRem: cardinal;
PipeSize: cardinal;
Security : TSecurityAttributes;
begin
Security.nlength := SizeOf(TSecurityAttributes) ;
Security.binherithandle := true;
Security.lpsecuritydescriptor := nil;
if CreatePipe(outputPipeRead, outputPipeWrite, @Security, 0) then
begin
SetStdHandle(STD_OUTPUT_HANDLE, outputPipeWrite);
end
else
showmessage ('Error in creating pipe');
.... Call dll here so that it sends output to stdout
PipeSize := Sizeof (textbuffer);
PeekNamedPipe (outputPipeRead, nil, PipeSize, @BytesRead, @PipeSize, @BytesRem);
if BytesRead > 0 then …Run Code Online (Sandbox Code Playgroud) 使用Python4Delphi,将Delphi方法暴露给Python非常简单,以便Python可以调用Delphi应用程序.但是我无法将由Delphi方法创建的Python列表返回给Python.例如:
function TDelphiAPI.callMethod : PPyObject;
begin
// Create a new empty list of three elements
result := GetPythonEngine.PyList_New(3);
end;
import mylib
p = mylib.DelphiAPI()
print p.callmethod()
Run Code Online (Sandbox Code Playgroud)
从Python调用时返回'NoneType'.如果将PPyObject更改为诸如整数,AnsiString或double之类的类型,则Python会选择正确的类型并正确显示它.我用
GetPythonEngine.AddMethod ('callMethod', @TDelphiAPI.callMethod, 'callMmethod)');
Run Code Online (Sandbox Code Playgroud)
从Delphi公开方法.但是,据我所知,没有办法为参数或返回类型指定类型.
我想知道是否有人从delphi python类型返回,如列表甚至numpy数组?
给定Delphi中的枚举类型声明,例如:
TMyType = (Item1, Item2, Item3);
Run Code Online (Sandbox Code Playgroud)
有没有办法在运行时将第四项(比如Item4)添加到枚举类型中,以便在应用程序执行期间的某个时刻我有:
TMyType = (Item1, Item2, Item3, Item4);
Run Code Online (Sandbox Code Playgroud)
或者是在Delphi中修复的类型?
我有一个C DLL,它返回一个指向由C DLL管理的PAnsiChar字符串的指针.我想制作一个字符串的副本,以便可以在Delphi端进行管理.
如果我将返回的PAnsiChar转换为AnsiString,就像在"str:= AnsiString(myPAnsiChar)"中那样,演员实际上做了什么?强制转换是否为PAnsiChar指向的字符串分配新内存,还是应该首先复制来自DLL的字符串?
我刚刚开始更熟悉界面是如何工作的,所以如果这是一个微不足道的问题请耐心等待.
我有两个插件(称为A和B)以DLL(不是包)的形式.在应用程序中声明了一个GUID的接口,它加载DLL,称之为IMyInterface.两个插件都使用相同的GUID查看相同的接口定义.插件B实际上实现了接口.
插件A想知道插件B是否支持接口IMyInterface.我使用obj.GetInterface(IMyInterface,IObj)来找出它:
var IObj : IMyInterface;
obj : TObject;
obj := getPluginObjReference;
if obj.GetInterface(IMyInterface, IObj) then
showmessage ('Interface Supported');
Run Code Online (Sandbox Code Playgroud)
如果我在插件B中调用此代码,答案是肯定的,这是预期的.如果我在插件A中使用相同的代码(剪切和粘贴),则相同的代码声称插件B不支持该接口.当我将GetInterface调用跟踪到system.pas时,我发现InterfaceEntry:= GetInterfaceEntry(IID); 返回nil,因此找不到接口.
作为参考,IMyInterface看起来像:
IMyInterface = interface
['{277A3122-A3F2-4A14-AE56-C99230F31CE9}']
function getModel : AnsiString;
function getDescription : AnsiString;
end;
Run Code Online (Sandbox Code Playgroud)
并且实现如下:
// Now the real class, this is private to this plugin
TModelAPI = class (TInterfacedObject, IMyInterface)
function getModel : AnsiString;
function getDescription : AnsiString;
end;
Run Code Online (Sandbox Code Playgroud)
等等
我的问题:
正如预期的那样,插件B正确声称支持IMyInterface.为什么Plugin A无法发现插件B支持IMyInterface?跨越DLL边界询问接口是否有问题?
delphi ×10
plugins ×2
dll ×1
enumeration ×1
firemonkey ×1
function ×1
interface ×1
rtti ×1
types ×1