0

I am trying to integrate with photo printer CHC-S6145 using C++ DLL S6145usb.dll. There is a function defined there as below. I want to know what is the mapping c# DLL import for that.

Function name - chcusb_getPrinterInfo

Format

BOOL APIENTRY chcusb_getPrinterInfo (WORD tagNumber, void *rBuffer, DWORD *rLen); 

Function details Obtain the information of the specified printer based on tag identifier.

1 Answers1

2

BOOL is a 32bit integer in Win32. PInvoke has a Boolean type, which can be marshaled as a 32bit integer via MarshalAs.

WORD is a 16bit unsigned integer. C# has a Uint16 type for that.

void* is a raw pointer. C# uses the (U)IntPtr type for that.

DWORD is a 32bit unsigned integer. C# has a UInt32 type for that.

DWORD*, on the other hand, is a pointer to a DWORD. C# has ref and out specifiers for passing a parameter variable by reference. Which one you need to use depends on whether the parameter is input/output (ref) or output-only (out).

Try something like this:

[DLLImport("S6145usb.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean chcusb_getPrinterInfo(UInt16 tagNumber, IntPtr rBuffer, ref UInt32 rLen);

...

UInt32 bufLen = ...;
IntPtr buffer = Marshal.AllocHGlobal((int)bufLen);
chcusb_getPrinterInfo(..., buffer, ref bufLen);
// use buffer as needed...
Marshal.FreeHGlobal(buffer);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    The final argument could be `ref` or `out`. Which one it is isn't reflected in the signature. That information needs to be spelled out in the accompanying documentation. – IInspectable Mar 08 '21 at 06:29
  • Thanks for your reply, When i am calling this how should i pass the IntPtr rBuffer parameter ? I mean should i create object of IntPtr and send ? – Asanka Dilruk Mar 10 '21 at 04:24
  • Function calling is working and it returns true (no errors) as well. But IntPtr will not get anything assigned. When i used below code it will return error saying source cannot be null. byte[] managedArray = new byte[28]; Marshal.Copy(intPtr, managedArray, 0, 28); – Asanka Dilruk Mar 10 '21 at 05:07
  • @AsankaDilruk the function is likely expecting you to allocate a buffer of sufficient size and then pass in a pointer to that buffer. You can use `Marshal.AllocHGlobal()` for that allocation. The `rLen` parameter is likely in/out, so you can specify the size of the buffer on input, and the function can return the size actually used on output. But you will have to check the function's documentation to verify that. – Remy Lebeau Mar 10 '21 at 05:31
  • @RemyLebeau, Thanks for all the support giving here. Yes you are correct rLen is the output size. For this specific tag (4) it will return 28 bytes according to the Spec. If you can give me small code sample to define IntPtr and allocate that 28 bytes and pass to the above method that will be helpful. – Asanka Dilruk Mar 10 '21 at 06:31
  • IntPtr intPtr = new IntPtr(28); Marshal.AllocHGlobal(intPtr); result = chcusb_getPrinterInfo(4, intPtr, out uint rLen); //Marshal.AllocHGlobal(intPtr); byte[] managedArray = new byte[28]; Marshal.Copy(intPtr, managedArray, 0, 28); -- This code returns object reference null exception when calling Marshal.Copy(intPtr, managedArray, 0, 28); – Asanka Dilruk Mar 10 '21 at 06:36
  • @AsankaDilruk you are close, try this: `IntPtr buffer = Marshal.AllocHGlobal(28); uint rLen = buffer.length; result = chcusb_getPrinterInfo(4, buffer, ref rLen); byte[] managedArray = new byte[rLen]; Marshal.Copy(buffer, managedArray, 0, rLen); Marshal.FreeHGlobal(buffer);` – Remy Lebeau Mar 10 '21 at 08:39
  • @RemyLebeau, It is working fine now. thanks for all the guide lines through the task. have a nice day ! – Asanka Dilruk Mar 10 '21 at 08:54