Jump to content
Sign in to follow this  
c0d3r

Need help: Variant in 64 bit application

Recommended Posts

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 by c0d3r

Share this post


Link to post
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
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 by Guest

Share this post


Link to post

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 by c0d3r

Share this post


Link to post
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 by c0d3r

Share this post


Link to post
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
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 by c0d3r

Share this post


Link to post
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
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
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;

 

  • Thanks 1

Share this post


Link to post
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×