-2

How would one "translate" following C++ function

LONG CALL_METHOD NET_SDK_Login(
    char *sDVRIP,
    WORD wDVRPort,
    char *sUserName,
    char *sPassword,
    LPNET_SDK_DEVICEINFO lpDeviceInfo);

to .Net (C#) to be used with P/Invoke? I tried with

[DllImport("DVR_NET_SDK.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int NET_SDK_Login(
    [MarshalAs(UnmanagedType.LPStr)] string sDVRIP,
    ushort wDVRPort,
    [MarshalAs(UnmanagedType.LPStr)] string sUserName,
    [MarshalAs(UnmanagedType.LPStr)] string sPassword,
    out _net_sdk_deviceinfo devinfo);

But no luck. Can anyone help?

Pieter Witvoet
  • 2,773
  • 1
  • 22
  • 33
nighthawk
  • 773
  • 7
  • 30
  • 1
    What error do you get? And what's the definition of `LPNET_SDK_DEVICEINFO`, `_net_sdk_deviceinfo` and `CALL_METHOD`? – Pieter Witvoet Jan 20 '15 at 07:54
  • As long as `CALL_METHOD` is `__stdcall` and `_net_sdk_deviceinfo` is declared correclty, I see no error in the definition. What's the error? (by the way, `__stdcall` is ignored in x64... are you sure the compiled library matches your target platform in .NET?) – Jcl Jan 20 '15 at 07:55
  • PieterWitvoet - LPNET_SDK_DEVICEINFO is pointer to struct that is "translated" correctly and _net_sdk_deviceinfo is that translated struct. CALL_METHOD is _stdcall. @Jcl - struct is declared correctly, i guess. Here is [link](http://pastebin.com/DXFPPyaR) c# code (with translated methods and structs) and source [link](http://pastebin.com/bKTJxZ47) of .dll I'm trying to import. There is no error - it simply won't connect to device. My guess is that something is of wrong type (IP address or username) and i can't connect. Demo app works fine, so device is ok. – nighthawk Jan 20 '15 at 08:10
  • Uhm, don't think that's the problem, but the code you pasted is using `ref` instead of `out` for the struct. If it doesn't throw any kind of runtime exception I guess the call is correct. Is the c# code you pasted the one giving the error, or the one that works? – Jcl Jan 20 '15 at 08:13
  • @Jcl - here is latest [c# code](http://pastebin.com/agj1Q31f) that kinda works. It just won't connect. I think that something gets lost in translation. Debugger doesn't throw any error that would point out that something is wrong (variable type or anything). When i enter wrong IP, it returns same code (-1) as with right IP. Because of that, i think that something gets translated wrong way. – nighthawk Jan 20 '15 at 08:20
  • @nighthawk note that you are using `192.168.001.132` as an IP. While technically it might be the same, it usually doesn't get translated the same by many libraries (including well-known ones: [example](https://social.msdn.microsoft.com/Forums/vstudio/en-US/21510004-b719-410e-bbc5-a022c40a8369/ipaddresstryparse-inconsistent-behavior-with-0-padded-values-on-certain-ip-addresses?forum=netfxbcl)) since they get the number as octal. Have you tried `192.168.1.132`? – Jcl Jan 20 '15 at 08:23
  • @Jcl - i tried with 192.168.1.132... Same result. Is rest of code ok? – nighthawk Jan 20 '15 at 08:27
  • The only difference I see is using `ref` instead of `out`. If the target platforms for the unmanaged DLL and the c# code are the same, I don't see anything obviously wrong. There might be other error actually connecting (username/password not matching? something else?) that is not necessarily a code problem – Jcl Jan 20 '15 at 08:28
  • Checked username, password, firewall.. Demo app connect just fine with same login data. I have no idea what's wrong... – nighthawk Jan 20 '15 at 08:34
  • You are using `ushort` for the port instead of `int` also. I'm assuming the first c# code you linked worked and the second one didn't, If so, why don't you just copy the signature from it and try? – Jcl Jan 20 '15 at 08:35

2 Answers2

1

The translation presented in the question is fine. The problem lies in your translation of the struct. As I explained in my answer to your previous question, you have not translated the struct correctly. You failed to translate the inline arrays in the struct.

For example, in the C++ version of the struct we see this field:

unsigned char deviceMAC[6]; 

You translated that as

byte deviceMAC;

That is a clear mistake. I'm sure that you realise that it is impossible to fit a 6 byte MAC address into a single byte.

That needs to be translated like this:

[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public byte[] deviceMAC;

And so on for all the other arrays in the struct.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Some comments on the question. The question does not present any relevant source. I mentioned this issue at your previous question. You have not addressed the problem there, nor here. I'm having to dig these struct definitions out of an off site link found in a different question. If you cannot edit this question to include the relevant details I would support voting to close and delete it. Please please try harder to make questions that stand alone. Finally, I already told you all of the detail about the inline arrays in the previous question. Why did you not heed the advice? – David Heffernan Jan 20 '15 at 09:05
  • Heffrnan - i didn't understand you. I am .Net dev, not C so for me, it's a quite a problem to translate these functions and structs to .Net equivalents. – nighthawk Jan 20 '15 at 10:52
  • [Here](http://pastebin.com/epKAZSmY) is altered version that still doesn't work. Deadline is near and nobody in my department can't translate this correctly. We tried dozen of solutions and this is closest we got. Could anyone check out this? @Jcl - not a single solution worked. This i closest we got and I'm sure that problem is in single line. One of parameters got translated wrong and i can't pinpoint what because only response i get is "-1" which means simply "Error". – nighthawk Jan 20 '15 at 11:02
  • Now what is wrong is that `char` in C# is two bytes wide. It's just a single byte wide in C on Windows. You have the code on both sides. Quite why you don't do some basic debugging is beyond me. I won't help you any more if you won't do what I ask with the question. It is not right that all the detail is hidden. – David Heffernan Jan 20 '15 at 11:15
  • @nighthawk I was assuming (as put on my first comment, to which you answered "yes") that the struct was correct and that the first c# code you posted actually worked. Taking this is the correct answer, then neither your struct was ok, nor the code you posted ran. Next time, be more precise when answering comments – Jcl Jan 20 '15 at 15:55
0

You could write some C++/CLI wrappers that will allow to call unmanaged code (C++) from C# (managed)

C# => C++/CLI => C++

You could take a look at this question and its anwser : C++/CLI: why should I use it?

Community
  • 1
  • 1
Camille G.
  • 3,058
  • 1
  • 25
  • 41