c# using const with DllImport - c#

I have a code example from a SDK, the DLL is written in C and calls for the following:
int getAttribute(const RawDevControl *control, RawDevAttribute *attribute)
I'm using
[DllImport(#"Dev.dll",
SetLastError = true)]
internal static extern int getAttribute(const RControl *control, RAttribute *attribute);
But of course you can not use const as a type when defining this reference function.
How can I make this work with c#?

Since C# doesn't have the concept of const references, you don't really need to worry about it. On the DLL side, the code will still think you have a const pointer. Thus, your import changes to this:
[DllImport(#"Dev.dll", SetLastError = true)]
internal static extern int getAttribute(RControl control, RAttribute attribute);
This, of course, assumes that both RControl and RAttribute have been defined in C#. If they are structs, follow the examples on MSDN for defining structs for use with P/Invoke. If they are classes, that's a different set of problems. In that case, it is best if the classes are COM-based.

The declaration promises that the function doesn't alter the passed object. So take advantage of that, tell the pinvoke marshaller that there's no point in copying it back. Apply the [In] attribute:
[DllImport(#"Dev.dll", SetLastError = true)]
static extern int getAttribute([In] ref RControl control, out RAttribute attribute);
Omit the ref or out keyword if you declared the argument types as classes instead of structs.

Related

Should I use the ref keyword here?

I'm new to C# so I looked at this question but I'm still not sure whether I should be including the ref keyword here when marshalling the second parameter of the GetWindoInfo() Win32 API call using p/invoke:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", EntryPoint = "GetWindowInfo", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetWindowInfo(IntPtr hwnd, [MarshalAs(UnmanagedType.Struct)] ref tagWINDOWINFO pwi);
From the MSDN documentation for ref:
The ref keyword causes an argument to be passed by reference, not by
value.
So in that case my code above seems to be correct, right? Would changing the marshalling clause to instead marshal an UnmanagedType.LPStruct and removing the ref keyword result in the same thing? Like so:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", EntryPoint = "GetWindowInfo", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetWindowInfo(IntPtr hwnd, [MarshalAs(UnmanagedType.LPStruct)] tagWINDOWINFO pwi);
From the MSDN documentation for GetWindowInfo function:
BOOL WINAPI GetWindowInfo(
_In_ HWND hwnd,
_Inout_ PWINDOWINFO pwi
);
EDIT:
As mentioned in the comments to the answer, the first code example is correct. The second code block is incorrect because passing by pointer and passing by reference are different and reflect a fundamental misunderstanding on my part. I was thinking of C++ dereferencing. See this question for more.
Yes, you should use the ref keyword for the struct.
First, there's a really great resource for P/Invoke definitions that you can find at www.pinvoke.net - and the particular method you're dealing with is documented here: http://www.pinvoke.net/default.aspx/user32.getwindowinfo. You'll see that it's defined using the ref keyword. This makes sense when you consider that the method is documented as _Inout_ for that parameter in the MSDN docs you linked.
The reason for this is that the ref keyword will allow that reference to be passed and have the struct you're dealing with before calling the method get updated/modified - rather than passing it in as is and never getting to see what the method actually does to it. In other words, without the ref keyword, your code would never see changes to the struct made within the GetWindowInfo call - GetWindowInfo would be working with its "own" copy of that structure.
If you want to read a bit more about why your second version wouldn't work, check out JaredPar's great explanation to What is the difference between a C# Reference and a Pointer?

typedef void* alternative in c#

I am using DLL runtime which is made with C language into C#.
I came across below statement.
typedef void *JCCP_PROPERTY_HANDLE;
In function it is being used as:
JCCP_RESULT __JCCP_FUNCTION__ jccpGetProperty(
JCCP_HANDLE hjccp,
const char *name,
JCCP_PROPERTY_HANDLE *phproperty);
Now I want to call jccpGetProperty() method in my C# code.
Can anybody tell how can I pass third parameter(JCCP_PROPERTY_HANDLE *phproperty) to function from C#.
I tried with below code but not working.
Extern Method:
[DllImport(DLL_NAME, EntryPoint = "_jccpGetProperty", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr jccpGetProperty(IntPtr hjccp, string name, ref IntPtr JCCP_PROPERTY_HANDLE);
Usage
IntPtr handle = IntPtr.Zero;
string tag = "server.version";
var result = jccpGetProperty(hjccp, tag, ref handle);
Can anybody help me in this?
IntPtr is the correct type mapping for void*. The native type void* is generally used for an opaque pointer, and that is mapped to IntPtr in C#.
Those parts of the p/invoke declaration that we can verify are correct. The unverifible parts are:
The calling convention. You believe that it is cdecl, but we can't check.
The return type. You believe it to be pointer sized. Again we cannot check. My guess is that a 32 bit integer, int or uint is more likely. That would make a difference in a 64 bit process.
The values passed to the function. It's perfectly possible that the function is declared correctly, but you are passing invalid values.
Because you only showed partial code and details, it's hard to say much more. You will have to verify all the parts of the program that we cannot.
I suggest that you start with working C or C++ code and translate that, looking for the first point of deviation in behaviour between that code and your C# translation.

Constraints vs abstract class using SafeHandle

There is a method within BCryptNative called GetInt32Property.
It has the following signature:
internal static int GetInt32Property<T>(T algorithm, string property) where T : SafeHandle
This method only works when T is of type SafeBCryptAlgorithmHandle or SafeBCryptHashHandle. It calls native methods which are explicitly defined with those types of handles:
[DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject,
string pszProperty,
[MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
int cbOutput,
[In, Out] ref int pcbResult,
int flags);
[DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetHashProperty(SafeBCryptHashHandle hObject,
string pszProperty,
[MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
int cbOutput,
[In, Out] ref int pcbResult,
int flags);
Microsoft uses function pointers / delegates to point to the correct native function. My question is, why didn't Microsoft just implemented the GetInt32Property method with the following signature:
internal static int GetInt32Property(SafeHandle algorithm, string property)
with the following native method:
[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetProperty(SafeHandle hObject,
string pszProperty,
[MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
int cbOutput,
[In, Out] ref int pcbResult,
int flags);
Are there any downsides to this? (assuming that the SafeHandle passed to GetInt32Property is always either a SafeBCryptAlgorithmHandle or SafeBCryptHashHandle).
I'm just wondering about why Microsoft implemented this so relatively complicated.
Does it have to with:
Security-Transparent Code?
Type safety? (So that you never use any other than those two types)
Is it allowed to use SafeHandle explicitly?
According to the documentation the class must be inherited, and it is, however does a P/Invoked function handle it properly when given an abstract class of SafeHandle? Does it increment and decrement the reference counts appropriately?
It's hard to tell why Microsoft chose to implement something in one way or another, but I can answer your points.
The code isn't complex. The usage is clear (something like GetInt32Property(algorithm, str).
It doesn't force you to send one of the types you mentioned, you can still call it with a different class, as long as it implements SafeHandle.
The native methods that are used are actually the same. This is kind of odd, but I'm not an expert on this specific library so it may be for a good reason.
There's a hidden benefit for generic methods like this one. The typeof(T) == typeof(SafeBCryptHashHandle) type checks are not done in runtime, but in JIT time. This means that the method should perform slightly faster then a regular runtime check like algorith is SafeBCrypthHashHandle.
The SafeHandle class is an abstract class. This means that you cannot create an instance of it, but you can inherit it. The native function only get marshaled data, they don't get real references to objects. Don't worry about reference counting.

When Importing a DLL Why Do Methods Have To Be Declared Static and Extern?

As the title asks, when you import a DLL such as User32.dll and declare methods to call methods on that DLL why do the methods need to be declared as Static and Extern.
I.E, this was taken from another StackOverflow answer, but demonstrates what I'm asking.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
static - As they do not need instance of the class, those method's are call to system API and do not need any Initialization, can be used in static / non-static block
extern - The extern modifier is used to declare a method that is implemented externally. Since API methods are not declared in the class file itself, extern tell the compiler that method declared else-where.
While I do not really know whether there are technical details to this, I'd say the reasons are:
static
Methods that reside in external DLLs can not be bound to any object instance. If they were bound to an object instance, the DLL would have to track which instance is calling the method every time.
extern
I guess this is just a keyword telling the compiler to insert code for binding the DLL instead of expecting the method to be implemented in C#.

Calling a custom type from a DLL written in C++ from c#

I'm using a DLL written in c++ in my C# project. I have been able to call functions within the DLL using this code:
[DllImport("hidfuncs", EntryPoint = "vm_hid_scan", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr VmHidScan();
Now I need to call a function that requres a custom type pointer. The Docs for the DLL layout the function like this:
hid_get_info(int n,PDEV_INFO *pdi)
I don't know how to use this custom pointer. Is this defined in the DLL? If so how can use it from C# project? If not do I need to include the header file in c#? Thanks in advance for your help.
Given the "P" prefix, it looks like the real declaration is
hid_get_info(int n, DEV_INFO **pdi)
where DEV_INFO is a structure. You'll need to find the declaration of this structure and add it to your C# code with the [StructLayout] attribute. You'd then declare the function like this in your C# code:
[DllImport("blah.dll")]
private static extern something hid_get_info(int n, out IntPtr pdi);
and use Marshal.PtrToStructure() to obtain the structure value. Hopefully you don't have to free the structure, you'd be screwed.
A second interpretation is that "pid" returns an array of pointers to DEV_INFO structures. Somewhat likely given the "n" argument, which could well mean the number of elements in the array you pass to be filled by the function. In that case, pass an IntPtr[] and set "n" to its Length.
You need to create a struct in C# that mirrors the C++ PDEV_INFO struct in C++.
You should apply [StructLayout(LayoutKind.Sequential)] to the struct and then copy the fields from the C++ struct (look at the header file) in order.
You can then write an extern method that takes the struct as a ref parameter.
I'll safely assume PDEV_INFO* is a DEV_INFO**.
Use this in C#:
class DEV_INFO
{
// fields go here
}
static class NativeMethods
{
[DllImport...]
public static extern int hid_get_info(int n, ref DEV_INFO pdi);
}

Categories

Resources