-1

I tried to use a C++ dll by fii,one of the function declared like this:

QCAP_CREATE( CHAR * pszDevName /*IN*/, UINT iDevNum /*IN*/, HWND hAttachedWindow /*IN*/, PVOID * ppDevice /*OUT*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );

I tried to pass a null pointer to the third parameter "hAttachedWindow " by ref like this:

const ffi = require('ffi');
const ref = require('ref');
const path = require('path');

let dllPath = path.join(__dirname, '/QCAP.X64');
let intPtr = ref.refType('int');

let QCAP = ffi.Library(dllPath, {
  'QCAP_CREATE': [ref.types.ulong, [ref.types.CString, ref.types.uint, 
  intPtr, intPtr, ref.types.bool, ref.types.bool]]
});

let ppdevice = ref.alloc('int');
let initResult = QCAP.QCAP_CREATE('CY3014 USB', 0, ref.NULL, ppdevice, true, false);

but the function keep throw an error said the third parameter is valid,I have imported this function in C# successfully like this,

    [DllImport(@"D:\01work\01code\video\code\VideoDemo\CPlusPlus\obj\Debug\QCAP.X64.DLL", EntryPoint = "QCAP_CREATE")]
    public static extern ulong QCAP_CREATE(string deviceName, UInt32 iDevNum, IntPtr hAttachedWindow, out IntPtr ppDevice, bool bThumbDraw, bool bMaintainAspectRatio);

    static void Main(string[] args)
    {
        try
        {
            public IntPtr ppDevice = new IntPtr(0x00000000);
            var result = QCAP_CREATE("CY3014 USB", 0, IntPtr.Zero, out ppDevice, true, false);
        }

I have checked the source code of ref ,it said that ref.NULL is

/** A Buffer that references the C NULL pointer. */

so I think ref.NULL equals IntPtr.Zero in C#,but it provides me wrong. I have googled for this problem quite a long time but nothing helped,can anyone give some suggestion to me? Many thanks!

Misland
  • 9
  • 3
  • 1
    So this is C# code calling C++ code? Please include the language you are writing the code in. – Yakk - Adam Nevraumont Jan 07 '19 at 14:12
  • I want to import and ues c++ function in node.js,but I have problems,the c# code is the sample that I use c++ function in c# – Misland Jan 07 '19 at 14:37
  • If you want to call C++ from C#, you have a C# question, because no-one who knows only C++ but not C# can help you with it. Can you add the tag for C# if that's what you want to use? Oh, also - can you explain what this error is, exactly? Is there an error message? It's always better to paste them in if possible. – Useless Jan 07 '19 at 15:05
  • You might want to look up what type a `HWND` is. The C# code appears to be treating it as a pointer to an `int`. In C++ (or whatever extension to C++ you're using) you probably need to provide a null pointer to `int` (i.e. an `int *` that is equal to null). There is no implicit conversion from a `X *` to an `int *` in C++, for `X` anything that is not an `int`. At a guess `ref.NULL` is probably a `void *`, not an `int *. – Peter Jan 07 '19 at 15:06
  • @Peter in C/C++, `HWND` is either a `void*` or a pointer to an opaque struct, depending on whether the code is compiled with `STRICT` enabled. In other languages, just treat it as a `void*` or equivalent. – Remy Lebeau Jan 07 '19 at 15:21
  • @RemyLebeau - yes, I know. But the code shown seems to be treating it differently. – Peter Jan 07 '19 at 16:02

1 Answers1

1

Part of the confusion you have is that the C# type IntPtr does not represent a "pointer to int", but instead a "pointer interpreted as int".

Another part is that after peeling back the aliases to the types involved, the third and fourth parameters are different pointer types, void * and void **. The C# binding hides this, because of the out qualifier passes the address of the IntPtr you allocate, allowing the library function to modify it.

Try this

const ffi = require('ffi');
const ref = require('ref');
const path = require('path');

let dllPath = path.join(__dirname, '/QCAP.X64');
let voidPtr = ref.refType(ref.types.void);
let voidPtrPtr = ref.refType(voidPtr);

let QCAP = ffi.Library(dllPath, {
  'QCAP_CREATE': [ref.types.ulong, [ref.types.CString, ref.types.uint, 
   voidPtr, voidPtrPtr, ref.types.bool, ref.types.bool]]
});

let ppdevice = ref.alloc(voidPtrPtr);
let initResult = QCAP.QCAP_CREATE('CY3014 USB', 0, ref.NULL, ppdevice, true, false);
let pdevice = ppdevice.deref();
Caleth
  • 52,200
  • 2
  • 44
  • 75