Playermet / codegoogle.tart

Automatically exported from code.google.com/p/tart
0 stars 0 forks source link

Unclear howto use Memory.zeroPtr #8

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
My goal is to retrieve the current username logged into Windows. The signature 
of the method is as follows (x86_64):

@Extern("GetUserNameW")
@LinkageName("x86_stdcallcc")
def GetUserNameW(buffer:Address[ubyte], size: uint32) -> int32;

As usual, the methods returns the length of the Unicode string if called with 
buffer = NULL and size = 0. How to create the first paramter? I tried the 
following:

import tart.core.Memory;

@EntryPoint
def main(args:String[]) -> int32 {
  let z1 = Memory.zeroPtr[ubyte]();
  let z2 = Memory.zeroPtr[Memory.Address[ubyte]]();
  return 0;
}

The first assignment results in:
BugTest3.tart:6: error: Compiled type mismatch for expression:zeroPtr()
info: Expected: 'i16'
info: Actual:   'i16*'
..\..\tart\trunk\compiler\lib\Gen\CodeGenExpr.cpp:289: Fatal error (Called from 
here)

The second produces a similar problem:
BugTest3.tart:7: error: Compiled type mismatch for expression:zeroPtr()
info: Expected: 'i16*'
info: Actual:   'i16**'
..\..\tart\trunk\compiler\lib\Gen\CodeGenExpr.cpp:289: Fatal error (Called from 
here)

Currently, I think that the signature of zeroPtr is wrong. It is defined as:

  @Intrinsic
  def zeroPtr[%ElemTy]() -> ElemTy;

but it should return a pointer. Therefore I would expect something like:

  @Intrinsic
  def zeroPtr[%ElemTy]() -> Address[ElemTy];

Original issue reported on code.google.com by kai.na...@gmail.com on 7 Dec 2010 at 5:44

GoogleCodeExporter commented 8 years ago
zeroPtr has changed a bit recently, I need to double-check what happened.

Ideally, there should be a better way to specify the calling signature of an 
external C function.

One thing you might try as an experiment is to declare the 'buffer' argument as 
'optional Address[ubyte]', so that the compiler will let you pass 'null' 
directly. (Although I'm not sure that 'optional' works with Address - I'll have 
to check.)

Original comment by viri...@gmail.com on 7 Dec 2010 at 5:49

GoogleCodeExporter commented 8 years ago
Great hint! Thank you.

With correct signature

@Extern("GetUserNameW")
def GetUserNameW(buffer:optional Address[uint16], size: Address[uint32]) -> 
int32;

I am able to call the function as follows

  var size: uint32 = 0;
  if GetUserNameW(null, addressOf(size)) != 0 {
    cerr.writeLn("Problem 1");
  }

and get the expected result :-)

Original comment by kai.na...@gmail.com on 7 Dec 2010 at 6:27