3

I am trying to call method available in C++ dll

HRESULT WINAPI TestMethod( _Out_ BOOL *isSuccess, _In_opt_ DWORD UsernmaeLength, _Out_opt_ LPWSTR userName ); 

Wrapper method Which I have written in C# looks like this

 [DllImport("Test.dll", CharSet = CharSet.Unicode, SetLastError = true ,CallingConvention = CallingConvention.StdCall)] public static extern int TestMethod ( IntPtr isSuccess, [In, Optional] int UsernmaeLength, out string userName ); 

I am calling this method in program

Wrapper. TestMethod (isSuccess, 200, out userName); 

I am getting System.AccessViolationException

tried changing the C# wrapper method with

[DllImport("Test.dll", CharSet = CharSet.Unicode, SetLastError = true ,CallingConvention = CallingConvention.StdCall)] public static extern int TestMethod ( bool isSuccess, [In, Optional] int UsernmaeLength, out string userName ); //Caller bool isSuccess = false; Wrapper. TestMethod (isSuccess, 200, out userName); 

Could you please help me to understand what I am doing wrong here?

7
  • You should try uint UsernmaeLength Commented Feb 22, 2018 at 8:32
  • And out IntPtr userName Commented Feb 22, 2018 at 8:35
  • I tried all the above 3 permutations, but NO Luck! Commented Feb 22, 2018 at 8:38
  • Try following: public static extern int TestMethod ( [Out] ref bool isSuccess, [In, Optional] uint UsernmaeLength, [Out, Optional] IntPtr userName ); Commented Feb 22, 2018 at 8:42
  • isSuccess is also out param Commented Feb 22, 2018 at 8:43

1 Answer 1

3
 _In_opt_ DWORD UsernmaeLength 

The SAL annotation is not very useful. What it probably is trying to tell you is that you can pass NULL for the string buffer argument. In which case what you pass for the buffer length doesn't matter. It is not actually [Optional], you'd consider simply passing 0 if you really don't want a string back.

The 3rd argument cannot be String or out since that is an immutable type and the function wants to write into the buffer you pass. It must be StringBuilder. The 2nd argument must be its Capacity. Be sure to make the StringBuilder big enough to fit a user name. If it is not then it isn't very obvious what will happen, hopefully the function then just returns an error code instead of silently truncating string. Test that.

The 1st argument is bool passed by reference, [Out] out bool. Not very likely that it SetLastError, that is only done by winapi functions. It already returns an error code embedded in the HResult. A value less than 0 is an error. Stdcall is the default. Summarizing:

[DllImport("Test.dll", CharSet = CharSet.Unicode)] public static extern int TestMethod ( [Out] out bool isSuccess, int userNameLength, StringBuilder userName ); 

Called as:

bool success; var name = new StringBuilder(666); int hr = TestMethod(out success, name.Capacity, name); if (hr < 0) Marshal.ThrowExceptionForHR(hr); 

If you still have trouble then you need the help of the author of this code if you cannot debug it yourself. Have a small repro available so he can easily repro the issue.

Sign up to request clarification or add additional context in comments.

1 Comment

you're awesome! :) It worked, Issue was the 3rd argument.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.