Just getting started with Nim and experimenting with Delphi interop. I can pass a Delphi interface reference (which is basically a pointer) into a Nim DLL and call methods on the interface using code like this for the definition:
type
GUID* {.pure.} = object
Data1*: int32
Data2*: uint16
Data3*: uint16
Data4*: array[8, uint8]
LONG* = int32
ULONG* = int32
IID* = GUID
REFIID* = ptr IID
HRESULT* = LONG
type
ITestIntfVtbl* {.pure, inheritable.} = ptr object # We don't want it managed by the GC so use ptr rather than ref.
QueryInterface*: proc (This: ptr ITestIntf; riid: REFIID; ppvObject: ptr pointer): HRESULT {.stdcall.}
AddRef*: proc (This: ptr ITestIntf): ULONG {.stdcall.}
Release*: proc (This: ptr ITestIntf): ULONG {.stdcall.}
TestProc1*: proc(This: ptr ITestIntf) {.stdcall.}
TestProc2*: proc(This: ptr ITestIntf) {.stdcall.}
ITestIntf* = object
lpVtbl*: ptr ITestIntfVtbl
ITestIntfRef* = ptr object
And this to use it:
import iunknown2
proc getRefCount*(intf: ITestIntf): int {.cdecl, exportc, dynlib.} =
intf.lpVtbl.TestProc1(cast[ptr ITestIntf](intf)) # Call the Delphi proc
var rtn: ULONG
rtn = 999 # Just return an int for testing
result = rtn
However, when I try the following to get an interface reference from a DLL function I get a nil pointer on the Delphi side:
import iunknown2
proc GetTestIntf*(): ITestIntfRef {.cdecl, exportc, dynlib.} =
var intf: ITestIntf
intf = ITestIntf()
result = cast[ptr ITestIntf](intf)
I'm obviously missing something here - can anyone see what I'm doing wrong?
Thanks, Bob
result = cast[ptr ITestIntf](intf) probably what you want is result = cast[ptr ITestIntf](intf.addr).
use addr operator to get the address of a variable.
returning something on the stack is very dangerous, the time you exit/returned from the proc, the object on the stack may be already replaced by something else or already gone.
maybe you should put in on global space