I'm importing several unmanaged c++ DLL's into my project however the imported DLLs have the same method name which causes compiler issues. For example;
unsafe class Myclass
{
[DllImport("myfirstdll.dll")]
public static extern bool ReturnValidate(long* bignum);
[DllImport("myseconddll.dll")]
public static extern bool ReturnValidate(long* bignum);
public Myclass
{
int anum = 123;
long passednum = &anum;
ReturnValidate(passsednum);
}
}
Now what I'd like to do would be rename the method on import. Something like;
[DllImport("myseconddll.dll")]
public static extern bool ReturnValidate(long bignum) AS bool ReturnValidate2(long bignum);
Is this possible?
Use the EntryPoint property of DllImport attribute.
[DllImport("myseconddll.dll", EntryPoint = "ReturnValidate")]
public static extern bool ReturnValidate2(long bignum);
Now when you call ReturnValidate2 in your C# code, you will effectively call ReturnValidate on myseconddll.dll.
You could provide any name for your imported function, you should only specify in DllImport the name of the function in it, using EntryPoint property. So you code could look like:
[DllImport("myfirstdll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate1(long bignum);
[DllImport("myseconddll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate2(long bignum);
Use the EntryPoint parameter:
[DllImport("myfirstdll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate1(long bignum);
[DllImport("myseconddll.dll", EntryPoint="ReturnValidate")]
public static extern bool ReturnValidate2(long bignum);
Documentation:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.entrypoint.aspx
Related
I have never created a P/Invoke wrapper method in C# because there's a way to do it "the managed way" using .NET Framework classes.
However, I have the need to invoke Win32 API function and I discovered that it's not as easy as I thought.
The function in IsWowProcess2, and the code to call it from C++ is illustrated here.
http://www.rudyhuyn.com/blog/2017/12/13/how-to-detect-that-your-x86-application-runs-on-windows-on-arm/
I've created a silly program to test it, but of course, it doesn't work:
class Program
{
static void Main(string[] args)
{
var result = IsWowProcess2();
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = false, PreserveSig = true)]
private static extern MyStruct IsWowProcess2();
}
internal class MyStruct
{
public ushort One { get; set; }
public ushort Two { get; set; }
}
What's the correct way to create the wrapper method and how to invoke it?
Start by reading the documentation. This gives the signature as:
BOOL IsWow64Process2(
HANDLE hProcess,
USHORT *pProcessMachine,
USHORT *pNativeMachine
);
As a pinvoke that is:
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool IsWow64Process2(
IntPtr process,
out ushort processMachine,
out ushort nativeMachine
);
I've no idea where your attempt came from but it looks nothing like the correct declaration, and in fact even the name of the function is wrong. Interop programming is all about detail and matching one binary interface to another. You don't get to invent the interface. Details like the parameters to be passed, the name of the function, etc. all need to match.
You can call it like this:
ushort processMachine;
ushort nativeMachine;
if (!IsWow64Process2(GetCurrentProcess(), out processMachine, out nativeMachine))
throw new Win32Exception();
You also need a declaration for GetCurrentProcess. You can use this:
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
The System.Windows.Forms.dll
I wish to wrap a few functions in this file in a C# class.
Specifically these: https://msdn.microsoft.com/en-us/library/system.windows.forms.cursor(v=vs.110).aspx
But I'm not sure how to get a list of functions. I've tried programs that returned no results. I was wondering if someone could give me 1 and only 1 example?
This, for example, returns an EntryPointNotFoundException
[DllImport("System.Windows.Forms.dll")]
public static extern void SetCursor(String s);
First, you need to enable interop services in order to call into windows functions:
using System.Runtime.InteropServices;
Then, you simply declare the methods that you want to import as such:
[DllImport("winmm.dll")]
public static extern bool PlaySound(string filename,long hmodule, int dword );
This creates a "mapping" to the PlaySound method in the unmanaged winmm.dll
The method is created as static and the use of the extern keywords tells the compilar that the method is external to your class (not running inside it)
To get list / search of unmanaged functions you can use
http://www.pinvoke.net
For instance, for SetCursor you can call
http://www.pinvoke.net/search.aspx?search=SetCursor&namespace=[All]
E.g. to place cursor at a position provided SetCursorPos you can do
using System.Runtime.InteropServices;
...
// Wrapper
class CursorNativeMethods {
[DllImport("User32.dll",
EntryPoint = "SetCursorPos",
CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean SetCursorPos(Point point);
...
[DllImport("User32.dll",
EntryPoint = "GetCursorPos",
CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean GetCursorPos([Out] out Point point);
...
}
// Your Routine
public static class MyCursor {
public Point Location {
get {
Point pt = new Point(-1, -1);
if (CursorNativeMethods.GetCursorPos(out pt))
return pt;
else
return new Point(-1, -1);
}
set {
CursorNativeMethods.SetCursorPos(value);
}
}
...
}
Please note, that System.Windows.Forms.dll is managed assembly (you should not interop with), and User32.dll is unmanaged library.
I'd like to know a way how to marshal 2 Classes that I made in C++ in C# language.
(a tutorial link would be perfect, I tried to google this for myself, but my english knowledge is not that advance, to search for the right thing. I am new to marshaling from C++ to C#)
Well basically what I have is something like this:
C++
EXPORT_API CarClass* DLL_AddCar();
EXPORT_API CarWheel* DLL_AddWheel();
EXPORT_API void DLL_GiveWheelToCar(CarClass* car,CarWheel* wheel);
C#
public class Car
{
#region Members
private IntPtr nativeCarObject;
#endregion Members
public Car()
{
this.nativeCarObject = Sim.DLL_AddCar();
}
// ---> this part is not working
//#region Wrapper methods
//public void GiveWheel(Wheel myWheel){Sim.DLL_GiveWheelToCar(this.nativeCarObject,myWheel);}
//#endregion Wrapper methods
}
public class Wheel
{
#region Members
private IntPtr nativeCarObject;
#endregion Members
public Wheel()
{
this.nativeCarObject = Sim.DLL_AddWheel();
}
}
internal class Sim
{
public const string pluginName = "MyDLL";
#region PInvokes
[DllImport(pluginName)] public static extern IntPtr DLL_AddCar();
[DllImport(pluginName)] public static extern IntPtr DLL_AddWheel();
[DllImport(pluginName)] public static extern void DLL_GiveWheelToCar(IntPtr car,IntPtr wheel);
#endregion PInvokes
}
Now My question is where would I use "DLL_GiveWheelToCar" ?
The method I tryed is commented out, because it didnt work, is it a logic error or should I change the way I'm marshaling?
Thanks for advice.
public void GiveWheel(Wheel myWheel){
Sim.DLL_GiveWheelToCar(this.nativeCarObject, myWheel);
}
Here you are passing myWheel which is of type Wheel to a function that expects an IntPtr. You need to pass the private field of the Wheel class that is currently (mis)named nativeCarObject.
Other points:
As I hinted above, the nativeCarObject member of Wheel should be renamed as nativeWheelObject.
The DLL looks like it uses the cdecl calling convention. You should specify that in your p/invoke declarations.
It looks like you code leaks the objects that the DLL supplies. I suspect you need to supply some tidy up helpers.
The code might look like something this:
public class Car
{
public readonly IntPtr nativeCarObject = Sim.DLL_AddCar();
public void GiveWheel(Wheel myWheel)
{
Sim.DLL_GiveWheelToCar(this.nativeCarObject, myWheel.nativeWheelObject);
}
}
public class Wheel
{
public readonly IntPtr nativeWheelObject = Sim.DLL_AddWheel();
}
internal class Sim
{
public const string pluginName = "MyDLL";
[DllImport(pluginName, CallingConvention=CallingConvention.Cdecl)]
public static extern IntPtr DLL_AddCar();
[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr DLL_AddWheel();
[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
public static extern void DLL_GiveWheelToCar(IntPtr car, IntPtr wheel);
}
This code is still leaking those objects. I'll let you sort that out.
How do you directly call a native function exported from a DLL? Can someone just give me a small example?
This is Microsoft example:
class PlatformInvokeTest
{
[DllImport("msvcrt.dll")]
public static extern int puts(string c);
[DllImport("msvcrt.dll")]
internal static extern int _flushall();
public static void Main()
{
puts("Test");
_flushall();
}
}
If you need to generate C# DLLImport declarations from a native dll, watch this post: Generate C# DLLImport declarations from a native dll
Depends on what exactly you want ... I have something like this in my code but this uses the Win32 API dll's
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
then just call
GetForegroundWindow()
as if defined inside the class
Here’s a quick example of the DllImport attribute in action:
using System.Runtime.InteropServices;
class C
{
[DllImport("user32.dll")]
public static extern int MessageBoxA(int h, string m, string c, int type);
public static int Main()
{
return MessageBoxA(0, "Hello World!", "Caption", 0);
}
}
This example shows the minimum requirements for declaring a C# method that is implemented in a native DLL. The method C.MessageBoxA() is declared with the static and external modifiers, and has the DllImport attribute, which tells the compiler that the implementation comes from the user32.dll, using the default name of MessageBoxA.
Refer this link
I have a C#.NET 2.0 CF application that imports a function from a native DLL with the following signature:
__declspec( dllexport ) void DLL_Foo( int count, ... );
My C# application P/Invokes that function as follows:
public sealed class MyObject
{
public void Foo()
{
NativeMethods.DLL_Foo(2, __arglist("a","b"));
}
internal static class NativeMethods
{
[DllImport("My.dll")]
internal static extern void DLL_Foo(int count, __arglist);
}
}
But, when I invoke MyObject.Foo, I get a System.MissingMethodException.
What do I need to change to make this work?
Thanks,
PaulH
Edit: If I change the import definition to:
internal static extern void DLL_Foo(int count, [MarshalAs(UnmanagedType.LPWStr)]string a, [MarshalAs(UnmanagedType.LPWStr)]string b);
then, call:
NativeMethods.DLL_Foo(2, "a", "b");
It works with no problems, so it's something with my __arglist usage.
I am not sure (and I have never done it) if you can have params args in P/Invoke but you might give it a try.
internal static extern void DLL_Foo(int count, params string[] args);
You should be using CallingConvention = CallingConvention.Cdecl for your DllImport. The CallingConvention.Cdecl description states it.
using LPWORD = System.IntPtr;
using LPVOID = System.IntPtr;
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern LPVOID extFunc(LPWORD lpdwMandatory,__arglist);
And then You can call extFunc function:
extFunc(lp1,__arglist( 0xFF,0x6A,0xAA));