Consider the following DllImport:
[DllImport("lulz.so")]
public static extern int DoSomething(IntPtr SomeParam);
This is actually referencing a C style function like this:
int DoSomething(void* SomeParam);
Consider that SomeParam is an "out" param, but can also be NULL. The C function behaves differently if the param is NULL. So I would probably want:
[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);
But, if I make it an out param in my import, I cannot pass it NULL, i.e. I can't do this:
int retVal = DoSomething(IntPtr.Zero)
What are my options here?
If you're trying to pass a value, then out is not the right keyword; change it to ref. You'll still need to explicitly pass a variable, but it can be a null reference.
For example...
[DllImport("lulz.so")]
public static extern int DoSomething(ref IntPtr SomeParam);
You can then call it like this:
IntPtr retVal = IntPtr.Zero;
DoSomething(ref retVal);
However
What is telling you that it needs to be either out or ref? Passing an IntPtr as out or ref is really akin to passing a double pointer. It would actually seem more appropriate to pass the parameter as an IntPtr.
The typical procedure is either to allocate the necessary memory in managed code and pass an IntPtr representing that allocated memory, or IntPtr.Zero to represent a null pointer. You do not need to pass the IntPtr as out or ref in order to send data back to .NET; you only need to do that if the function you're calling would actually change the pointer's address.
I don't understand what the problem is....
This runs:
private void button2_Click(object sender, EventArgs e) {
object bar;
Method(out bar);
bar = IntPtr.Zero;
Method(out bar);
}
private void Method(out object foo) {
foo = null;
}
What's the intention of passing NULL? Is it intended to call the method as usual, but to simply not set the output parameter?
In that case, I think I'd just wrap the extern method with an overload in C#. That overload (without the out parameter) would be like this:
public void DoSomething()
{
IntPtr dummy;
DoSomething(out dummy);
}
I ran into this once. I ended up marshaling the pointer myself (see Marshal Members for the library functions to do so).
Personally, I'd import this function twice, first time with 'out' parameter, second with 'in'.
[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);
// call as DoSomethingWithNull(IntPtr.Zero)
[DllImport("lulz.so", EntryPoint="DoSomething")]
public static extern int DoSomethingWithNull(IntPtr SomeParam);
This will solve your problem and will make code more readable.
Related
Let's say I have IntPtr variable, its value has been assigned via call of WinApi function (p/invoke). Then I passed that value in 10 different functions. Since IntPtr is struct (value type), each function will get a copy of the original variable. Will it cause memory leak? Should I close each copy of the original variable in each function?
[DllImport("WinApiFunction")]
public static extern bool WinApiFunction(int arg1, int arg2, out IntPrt result)
public void Foo()
{
var result = IntPtr.Zero;
WinApiFunction(1, 2, out result);
Foo1(result);
Foo2(result);
Foo3(result);
//...
Foo10(result);
// ...
CloseHandle(result);
}
IntPtr is often used as a place holder for handle or pointer values. It's hard to tell from the code exactly what is happening but copying a handle or pointer value wouldn't copy the underlying resource.
So in your example it seems correct to CloseHandle once. I would put it into a try..finally though to ensure that CloseHandle is always called if WinApiFunction returned a valid handle.
[DllImport("WinApiFunction")]
public static extern bool WinApiFunction(int arg1, int arg2, out IntPrt result)
public void Foo()
{
var result = IntPtr.Zero;
if (!WinApiFunction(1, 2, out result) || result == IntPtr.Zero)
{
throw new Exception("Oops");
}
try
{
Foo1(result);
Foo2(result);
}
finally
{
CloseHandle(result);
}
}
If you would build a proxy class around the handle this the use case to implement a finalizer (and IDisposable) on the proxy class.
I have multiple projects in a Visual Studio 2015 solution. Several of these projects do P/Invokes like:
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
public static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)]
ref int pdwSize, bool bOrder);
So I moved all my P/Invokes to a separate class library and defined the single class as:
namespace NativeMethods
{
[
SuppressUnmanagedCodeSecurityAttribute(),
ComVisible(false)
]
public static class SafeNativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int GetTickCount();
// Declare the GetIpNetTable function.
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
public static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)]
ref int pdwSize, bool bOrder);
}
}
From the other projects, this code is called as:
int result = SafeNativeMethods.GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false);
All compiles without error or warning.
Now running FxCop on the code gives the warning:
Warning CA1401 Change the accessibility of P/Invoke
'SafeNativeMethods.GetIpNetTable(IntPtr, ref int, bool)' so that it is
no longer visible from outside its assembly.
Ok. Changing the accessibility to internal as:
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
internal static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)]
ref int pdwSize, bool bOrder);
Now causes the hard error of:
Error CS0122 'SafeNativeMethods.GetIpNetTable(IntPtr, ref int, bool)'
is inaccessible due to its protection level
So how can I make this work without error or warning?
Thanks in advance for any help as I've been going in circles for hours!
It is a sure thing that you will agree with statement that PInvoke methods are not the most pleasant things to call from C# code.
They are:
Not so strongly typed - often riddled with IntPtr and Byte[] parameters.
Error prone - it is easy to pass some incorrectly initialized parameter, like a buffer with wrong length, or some struct with field not initialized to that struct's size...
Obviously don't throw exceptions if something goes wrong - it is their consumer's responsibility to check the return code or Marshal.GetLastError() it. And more often then not, someone forgets to do it, leading to hard-to-track bugs.
In comparison with these issues FxCop warning is but a meager style checker peeve.
So, what can you do? Deal with those three issues and FxCop will go by itself.
These are the things I recommend you to do:
Do not expose any API directly. It is important for complex functions, but applying it for any function will actually deal with your primary FxCop issue:
public static class ErrorHandling
{
// It is private so no FxCop should trouble you
[DllImport(DllNames.Kernel32)]
private static extern void SetLastErrorNative(UInt32 dwErrCode);
public static void SetLastError(Int32 errorCode)
{
SetLastErrorNative(unchecked((UInt32)errorCode));
}
}
Don't use IntPtr if you can use some safe handle.
Don't just return Boolean or (U)Int32 from wrapper methods - check for return type inside the wrapper method and throw the exception if required. If you want to use a method in exception-less manner, then provide Try-like version that will clearly denote that it is a no-exception method.
public static class Window
{
public class WindowHandle : SafeHandle ...
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport(DllNames.User32, EntryPoint="SetForegroundWindow")]
private static extern Boolean TrySetForegroundWindowNative(WindowHandle hWnd);
// It is clear for everyone, that the return value should be checked.
public static Boolean TrySetForegroundWindow(WindowHandle hWnd)
{
if (hWnd == null)
throw new ArgumentNullException(paramName: nameof(hWnd));
return TrySetForegroundWindowNative(hWnd);
}
public static void SetForegroundWindow(WindowHandle hWnd)
{
if (hWnd == null)
throw new ArgumentNullException(paramName: nameof(hWnd));
var isSet = TrySetForegroundWindow(hWnd);
if (!isSet)
throw new InvalidOperationException(
String.Format(
"Failed to set foreground window {0}",
hWnd.DangerousGetHandle());
}
}
Don't use IntPtr or Byte[] if you can use normal structs passed by ref/out. You may say that it is obvious, but in many cases where a strongly typed struct can be passed I have seen IntPtr being used instead. Don't use out parameters in your public-facing methods. In most cases it is unnecessary - you can just return the value.
public static class SystemInformation
{
public struct SYSTEM_INFO { ... };
[DllImport(DllNames.Kernel32, EntryPoint="GetSystemInfo")]
private static extern GetSystemInfoNative(out SYSTEM_INFO lpSystemInfo);
public static SYSTEM_INFO GetSystemInfo()
{
SYSTEM_INFO info;
GetSystemInfoNative(out info);
return info;
}
}
Enums. WinApi uses a lot of enum values as parameters or return values. Being a C style enum they are actually passed(returned) as simple integers. But C# enums are actually nothing more than integers too, so assuming that you have set proper underlying type, you will have much easier to use methods.
Bit/Byte twiddling - whenever you see that getting some values or checking their correctness requires some masks, then you can be sure that it can be better handled with custom wrappers. Sometimes it is handled with FieldOffset, sometimes a bit of actual bit twiddling should be done, but in any case it will be done only in one place, providing simple and handy object model:
public static class KeyBoardInput
{
public enum VmKeyScanState : byte
{
SHIFT = 1,
CTRL = 2, ...
}
public enum VirtualKeyCode : byte
{
...
}
[StructLayout(LayoutKind.Explicit)]
public struct VmKeyScanResult
{
[FieldOffset(0)]
private VirtualKeyCode _virtualKey;
[FieldOffset(1)]
private VmKeyScanState _scanState;
public VirtualKeyCode VirtualKey
{
get {return this._virtualKey}
}
public VmKeyScanState ScanState
{
get {return this._scanState;}
}
public Boolean IsFailure
{
get
{
return
(this._scanState == 0xFF) &&
(this._virtualKey == 0xFF)
}
}
}
[DllImport(DllNames.User32, CharSet=CharSet.Unicode, EntryPoint="VmKeyScan")]
private static extern VmKeyScanResult VmKeyScanNative(Char ch);
public static VmKeyScanResult TryVmKeyScan(Char ch)
{
return VmKeyScanNative(ch);
}
public static VmKeyScanResult VmKeyScan(Char ch)
{
var result = VmKeyScanNative(ch);
if (result.IsFailure)
throw new InvalidOperationException(
String.Format(
"Failed to VmKeyScan the '{0}' char",
ch));
return result;
}
}
P.S.: And do not forget about correct function signatures (bitness and other issues), marshaling of types, layout attributes and char set (also, not forgetting to use DllImport(... SetLastError = true) is of utmost importance). http://www.pinvoke.net/ may often help, but it doesn't always provide the best signature to use.
P.S.1: And I recommend you to organize your NativeMethods not into one class , because it will quickly become one huge unmanageable pile of quite different methods, but instead to group them into separate classes (I actually use one partial root class and nested classes for each functional area - a bit more of tedious typing, but much better context and Intellisense). For class names I just use the same classification MSDN uses to group API functions. Like for GetSystemInfo it is "System Information Functions"
So, if you apply all those advises, you will be able to create a robust, easy to use native wrapper library that hides all the unnecessary complexities and error-prone constructs, but that will look very familiar to anyone who knows the original API.
I have the following PInvoke:(C to C#)
[DllImport("chess_api.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void InitBoard([MarshalAs(UnmanagedType.LPArray, SizeConst = 64)]sPiece[] board);
On C:
__declspec(dllexport) void InitBoard(sPiece board[8][8]);
In InitBoard function, the values of the matrix changing, but after a call to PInvoke I do not see the change.
sPiece[] board = new sPiece[64];
InitBoard(board);
//Here the values of the board is still initialized (as before the function call) at default values
I tried to change the variable to ref (although it already reference) but it stuck the program when the function was called, so I do not think it's the solution.
It took me a while to get here (I'm new to the subject) I'd love to help!
EDIT:
sPiece On C:
typedef struct Piece
{
ePieceType PieceType; //enum
ePlayer Player; //enum
int IsFirstMove;
} sPiece;
sPiece On C#:
[StructLayout(LayoutKind.Sequential)]
public struct sPiece
{
public ePieceType PieceType;
public ePlayer Player;
public int IsFirstMove;
}
Possibly you are failing to allocate memory before calling the function.
sPiece[] board = new sPiece[64];
InitBoard(board);
Declare the function like this:
[DllImport("chess_api.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void InitBoard([Out] sPiece[] board);
The default marshalling is [In]. Although since your struct is blittable, the array you pass is pinned and the call behaves as though it was [In,Out]. So I think you could omit [Out] if you wished, but it is clearer as written above.
You can add the UnmanagedType.LPArray option if you wish but it's not needed.
I'm trying to pass .NET array to COM VB6 library. I have an object which is COM wrapper of VB6 object. It has method with the following signature:
[MethodImpl(MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime)]
void AddEx([MarshalAs(UnmanagedType.Struct)] object vSafeArrayOfItems);
but when I call it I get an ArgumentException with the following message:
Value does not fall within the expected range.
The type of exception and its description doesn't even depend on passed element.
Does anybody know how to go around this issue?
UPD: I removed .NET wrapper assemblies and referrenced source .COM libraries. No changes had happened.
You would need to mirror the VB6 struct format:
[StructLayout(LayoutKind.Sequential)]
public struct myStruct {
type1 member1;
type2 member2;
}
To import the function you would have to do:
[DllImport("dllname.dll")]
public static extern void AddEx(IntPtr paramName);
You can easily use the following functions to perform struct <-> IntPtr conversions:
myStruct struct = Marshal.PtrToStructure(paramName, typeof(myStruct));
// do stuff
Marshal.StructureToPtr(struct, paramName, false);
Edit: I misread what you wanted to do. But this is a starter for doing the interop.
The argument exception comes from trying to send a reference type as a value type. (object is a class, structs are handled differently)
If you want to pass an array you would do:
void AddEx([MarshalAs(UnmanagedType.LPArray)] ref myStruct[] param);
I think you could write the external method declaration like the following:
[DllImport...
public static extern void AddEx(YourType[] paramName);
//or like the following:
public static extern unsafe void AddEx(YourType * paramName);
I am trying to create a wrapper to a C dll and I am trying to call a function that has takes a callback function, receives an object as a pointer that is passed back.
The .h file delares
extern int SetErrorHandler(void (*handler) (int, const char*, void*),
void *data_ptr);
The handler is a callback function that is called when an error occurs and the data_ptr is any object (state) that is passed back to you, in the case of my app that will just be this (current object).
I am able to call functions in a dll that uses marshalled constant types like simple types strings, ints etc. But I cant figure out how to just marshall a pointer to a C# object that is the state.
In order to pass the object reference to the C function from what I have find by searching here and otherwise it seems that I need a structure type to be able to marshall to the function so I created a struct to hold my object:
[StructLayout(LayoutKind.Sequential)]
struct MyObjectState
{
public object state;
}
EDIT: I tried to put an attribute: [MarshalAs(UnmanagedType.Struct, SizeConst = 4)] on the public object state property, but this produces the same error, so I removed it, doesnt seem it would work anyway.
The struct contains a single object property to hold any object for the callback function.
I declared the delegate in C# as follows:
delegate void ErrorHandler(int errorCode, IntPtr name, IntPtr data);
Then I declared the import function in C# as follows:
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int SetErrorHandler handler, IntPtr data);
Then I created a callback function in my C# code:
void MyErrorHandler(int errorCode, IntPtr name, IntPtr data)
{
var strName = Marshal.PtrToStringAnsi(name);
var state = new MyObjectState();
Marshal.PtrToStructure(data, state);
Console.WriteLine(strName);
}
I am able to call the library function as follows:
var state = new MyObjectState()
{
state = this
};
IntPtr pStruct = Marshal.AllocHGlobal(Marshal.SizeOf(state));
Marshal.StructureToPtr(state, pStruct, true);
int ret = SetErrorHandler(MyErrorHandler, pStruct);
The call works and the callback function is called but I am unable to access the data in the callback function and when i try Marshal.PtrToStructure I get an error:
The structure must not be a value class.
I did a lot of searching here and found various things on Marshall and void* but nothing has helped me to get this to work
Thanks.
You are making this more complicated than it needs to be. Your C# client does not need to use the data_ptr parameter because a C# delegate already has a built in mechanism for maintaining the this pointer.
So you can simply pass IntPtr.Zero to the delegate. Inside your error handler delegate you just ignore the value of data_ptr since this will be available.
In case you don't follow this description, here's a short program to illustrate what I mean. Note how MyErrorHandler is an instance method that acts as the error handler, and can modify instance data.
class Wrapper
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void ErrorHandler(int errorCode, string name, IntPtr data);
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int SetErrorHandler(ErrorHandler handler, IntPtr data);
void MyErrorHandler(int errorCode, string name, IntPtr data)
{
lastError = errorCode;
lastErrorName = name;
}
public Wrapper()
{
SetErrorHandler(MyErrorHandler, IntPtr.Zero);
}
public int lastError { get; set; }
public string lastErrorName { get; set; }
}
class Program
{
static void Main(string[] args)
{
Wrapper wrapper = new Wrapper();
}
}
There may very well be a way to do this, but I gave up a long time ago. The solution I've come up with is slightly hackish, but it's very effective and works with everything I've thrown at it:
C# -> Managed C++ -> Native calls
Doing it this way you end up writing a small wrapper in managed C++, which is kind of a pain, but I found to be more capable and less painful than all of that marshaling code.
Honestly though I'm kind of hoping that someone gives a non-evasive answer, I've struggled with this for quite a while myself.