c0d3r 17 Posted November 17, 2020 (edited) Hi, All I got very confused for the following code which is working in our 32 bit application but not in 64 bit application (using Delphi 10.4.1): function TMyService.Init(const ClientIdent: TkbmMWClientIdentity; const Args: array of Variant): Variant; var ds: TDataset begin Result := ''; <---- raising "Invalid variant type" in 64 bit application ... end; Any idea? Thanks. Edited November 17, 2020 by c0d3r Share this post Link to post
Anders Melander 1815 Posted November 17, 2020 24 minutes ago, c0d3r said: Any idea? Run it through the debugger: Set a break point on the line and "step into" the assignment. Make sure you compile with debug dcus. Share this post Link to post
Guest Posted November 17, 2020 (edited) 31 minutes ago, c0d3r said: Hi, All I got very confused for the following code which is working in our 32 bit application but not in 64 bit application (using Delphi 10.4.1): ... Result := ''; <---- raising "Invalid variant type" in 64 bit application ... Any idea? Thanks. here in RAD 10.4.1 all it's ok implementation {$R *.dfm} function fncReturnVariantType1(lVariant: Variant): Variant; begin result := lVariant; end; function fncReturnVariantType2: Variant; begin // all ok result := ''; // result := 1; // result := 2.31; //result := now; end; procedure TForm1.Button1Click(Sender: TObject); var lMyString: string; begin // all ok! lMyString := fncReturnVariantType1('a'); lMyString := fncReturnVariantType1(1); lMyString := fncReturnVariantType1(2.31); lMyString := fncReturnVariantType1(now); // caption := lMyString; // // exit; // ok! lMyString := fncReturnVariantType2; // caption := lMyString; //or caption := fncReturnVariantType2; end; Edited November 17, 2020 by Guest Share this post Link to post
c0d3r 17 Posted November 17, 2020 (edited) Just want to make it clear. This is a Windows service project, includes several Micro services that serve client requests. Here are what we have in codes: Type TServerServiceMethod = function(Sender: TObject; const ClientIdent: TkbmMWClientIdentity; const Args:array of Variant): variant; Function to process client request, the result will be send back to client: function TMybaseService.ProcessRequest(const Func: string; const ClientIdent: TkbmMWClientIdentity; const Args: array of Variant): Variant; var ServiceMethod: TServerServiceMethod; begin @ServiceMethod := MethodAddress(Func); if Assigned(ServiceMethod) then Result := ServiceMethod(Self, ClientIdent, Args) else Result := inherited ProcessRequest(Func, ClientIdent, Args); end; The problem code is one of the micro service method defined in the service's Published section: function TMyService.Init(const ClientIdent: TkbmMWClientIdentity; const Args: array of Variant): Variant; var ds: TDataset begin Result := ''; <---- raising "Invalid variant type" in 64 bit application ... end; The codes were working in 32 bit application, so I was wondering if there is something missing in the above ProcessRequest in 64 bit, but don't know what I'm missing. Edited November 17, 2020 by c0d3r Share this post Link to post
c0d3r 17 Posted November 17, 2020 (edited) 1 hour ago, Anders Melander said: Run it through the debugger: Set a break point on the line and "step into" the assignment. Make sure you compile with debug dcus. Odd, the initial Result.VType = 48088, variant array of unknown, What was that?! Edited November 17, 2020 by c0d3r Share this post Link to post
Anders Melander 1815 Posted November 17, 2020 27 minutes ago, c0d3r said: Odd, the initial Result.VType = 48088, variant array of unknown, What was that?! Strange. Could be caused by a previous stack or heap corruption, maybe in the calling method. Or it could simply be a compiler bug. I don't think it's one that I've heard of though. If it's not evident, looking at the source, where the value comes from you can try to trace through the assembler in the CPU view to determine it. Also make sure to do a full build to ensure that there isn't a dcu mismatch somewhere. Share this post Link to post
c0d3r 17 Posted November 17, 2020 (edited) 47 minutes ago, Anders Melander said: Strange. Could be caused by a previous stack or heap corruption, maybe in the calling method. Or it could simply be a compiler bug. I don't think it's one that I've heard of though. If it's not evident, looking at the source, where the value comes from you can try to trace through the assembler in the CPU view to determine it. Also make sure to do a full build to ensure that there isn't a dcu mismatch somewhere. I'm looking into: @ServiceMethod := MethodAddress(Func) and ServiceMethod(Self, ClientIdent, Args) wondering if it works for 64 bit or not. when I trace to the actual method code, all the properties in that "Self" is all reset, which tells me the 'Self' isn't the one. Edit: WOW, something is wrong for sure, in that TMyService.Init method, calling a class function got 'c0000005 ACCESS_VIOLIATION' error: class function TMyService.GetPrefServceName: string begin Result := 'ABC'; end; function TMyService.Init(const ClientIdent: TkbmMWClientIdentity; const Args: array of Variant): Variant; var ds: TDataset S: string; begin s := GetPrefServiceName; <---- raising "c0000005 ACCESS_VIOLATION" in 64 bit application ... end; Edited November 17, 2020 by c0d3r Share this post Link to post
Anders Melander 1815 Posted November 17, 2020 24 minutes ago, c0d3r said: I'm looking into: @ServiceMethod := MethodAddress(Func) and ServiceMethod(Self, ClientIdent, Args) wondering if it works for 64 bit or not. I think you'll have to ask @Kim Madsen for help on this one. I would imagine that it's supposed to work with 64-bit but since I don't have the source I can't tell. Share this post Link to post
c0d3r 17 Posted November 17, 2020 1 minute ago, Anders Melander said: I think you'll have to ask @Kim Madsen for help on this one. I would imagine that it's supposed to work with 64-bit but since I don't have the source I can't tell. These 2 lines codes aren't related to kbmMW, they are delphi RTTL related codes, that you can call all the published methods in a class. @ServiceMethod := MethodAddress(Func) ServiceMethod(Self, ClientIdent, Args) Share this post Link to post
Anders Melander 1815 Posted November 17, 2020 31 minutes ago, c0d3r said: These 2 lines codes aren't related to kbmMW, they are delphi RTTL related codes, that you can call all the published methods in a class. Ah yes. Shouldn't TServerServiceMethod be declared like this then: type TServerServiceMethod = function(Sender: TObject; const ClientIdent: TkbmMWClientIdentity; const Args:array of Variant): variant of object; (add "of object") Also I think you need to call it like this: var ServiceMethod: TMethod; begin ServiceMethod.Data := Self; ServiceMethod.Code := MethodAddress(Func); TServerServiceMethod(ServiceMethod)(Self, ClientIdent, Args); end; 1 Share this post Link to post
c0d3r 17 Posted November 17, 2020 1 hour ago, Anders Melander said: Ah yes. Shouldn't TServerServiceMethod be declared like this then: type TServerServiceMethod = function(Sender: TObject; const ClientIdent: TkbmMWClientIdentity; const Args:array of Variant): variant of object; (add "of object") Also I think you need to call it like this: var ServiceMethod: TMethod; begin ServiceMethod.Data := Self; ServiceMethod.Code := MethodAddress(Func); TServerServiceMethod(ServiceMethod)(Self, ClientIdent, Args); end; Yes. That was it. Thanks much! Share this post Link to post