Let's assume I have an unmanaged class Test:
class Test
{
public:
int SomeMethod(int a, bool b);
};
To create a new instance of Test, I'd:
Test *test = new Test();
My goal is to embed Mono so that managed code could call unmanaged methods (like Test::SomeMethod) in a specific object. I represent that object by passing a pointer of that object to the managed method, like that:
void *args[1];
args[0] = &test;
mono_runtime_invoke(init, NULL, args, NULL);
Here is how the managed method that is being invoked looks like:
public static void Init(IntPtr test)
{
}
From here, how can I call Test.SomeMethod?
I thought about using emitting the CALLI instruction, using System.Reflection.Emit, but how can I refer to the object that the pointer test (the first parameter of Init) is referring to?
I do not want to use DllImport.
You might be interested in CXXI. It creates a managed assembly based on your C++ headers and allows you to work with C++ objects as if they were normal managed objects.
As far as I understand it, it's not finished yet and works only with C++ code compiled by GCC.
Can't be done (Or at least shouldn't be done).
You're trying to directly mix two completely different execution environments - the reason why DLLImport exists is to allow the compiler to solve this problem.
In .NET, you can create mixed-mode applications (C++/CLI) which allow managed code and unmanaged code to co-exist in the same binary (and call each other), but since you're talking about mono, I'm assuming that option is out.
Managed environments like .NET have strict type rules, garbage collection and other features that simply don't work with unmanaged code and data.
You can use an internal call, if you don't want to use DllImport.
See https://github.com/mono/mono/blob/master/samples/embed/teste.c the mono_add_internal_call() invocation and the C# code in the test.cs file.
This works mostly like DllImport, except there is no marshalling done for you (a string object in C# code will appear as a MonoString* in the C code, not as a char*, for example).
In any case, note that both the function you could access with DllImport and the function pointer registered with mono_add_internal_call() must be C functions, not C++ member methods.
Related
I am currently using PInvoke to call some unmanaged functions from C++ in C#; specifically from PhysX 3.3.3. I am relatively new to PInvoke so I started with some simple methods. I can easily call functions that take no parameters but am having trouble calling any that do.
Starting simple, I used a function that passed in a boolean and discovered that booleans are non-blittable types so they must be marshaled. However, adding the boolean marshaling to the PInvoke signature still did not work.
[DllImport("PhysX3CommonCHECKED_x64.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?getReportAllocationNames#Foundation#shdfnd#physx##UEBA_NXZ")]
public static extern bool GetAllocationNames();
[DllImport("PhysX3CommonCHECKED_x64.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?setReportAllocationNames#Foundation#shdfnd#physx##UEAAX_N#Z")]
public static extern void SetAllocationNames([MarshalAs(UnmanagedType.U1)]bool name);
When I call SetAllocationNames(true), I get an AccessViolationException. I have also tried using other member names for the UnmanagedType enumeration (e.g. U1, Bool) but to no avail.
I am loading the DLLs prior to calling the functions, I am using the correct mangled name as the entry point, and I am calling all parameters associated with this function (just one in this case). Is there something else I'm missing?
Unfortunately, it is mostly impossible to share C++ libraries with other C++ applications if they were compiled with a different compiler (and even worse, different versions of the same compiler) , yet alone using PInvoke.
Secondly, you're not even close at tackling this problem. C++'s calling convention (in x86) for methods (functions that belong to a class) is thiscall, which means that this (the class the method is called upon) is passed via the ecx or rcx register. cdecl doesn't pass one. Secondly, you didn't even define the appropriate classes...
What you should do is to write a C++ wrapper
Write functions, not methods (i.e - not bound to any class or struct), that do whatever you need to be done, and make sure that you know their calling convention (make it something conventional, like cdecl or fastcall). This way you can write C/C++ code to do the work for you, and write C# with PInvoke.
Okay, I think I understand now. After further research, it does seem that inherited functions are problematic for PInvoke. Many sources recommend flattening the C++ code to a C style interface. I will have to use a C++/CLI project instead. Thanks!
I have an unmanaged DLL that exports C style non-member functions for creating (say CreateObject) and destroying objects (DestroyObject). CreateObject returns a C++ class as a void*, which in the unmanaged code is cast to a known interface (defined only in a header file) and worked with. Is there a way to call methods on the IntPtr that is returned to me by CreateObject?
Dumpbin /EXPORT doesn't show me any methods of the C++ class, just the exported C functions (mentioned above).
I would like to avoid having to write C++ CLI code or a purely unmanaged DLL that simply exposes methods on this class as function wrappers if possible
This is Windows/MSVC only, so answers that restrict compatibility to Windows/MSVC are fine.
NOTE: I'm talking about invoking C++ methods on a void*/IntPtr returned by a C function - not P/Invoking the C functions.
Thanks!
If you are ruling out C++/CLI, and only have an IntPtr containing the address of the instance then you have few options remaining.
As I see it you are left with p/invoke. In order to call a method you'll need to export it from your unmanaged code. You'll also need to be careful about the calling convention. Commonly it will be __thiscall. When you write the p/invoke, you must explicitly add the this pointer as the first parameter.
This is fine so far as it goes. But you'll not be able to export virtual methods this way. You cannot call them using p/invoke.
Frankly though the cleanest and simplest way to do this interop is with our old friend, tried and tested COM. This very scenario is just what it was designed for. C++ classes are not designed for interop across compiler/language boundaries. That's what COM is for.
I have a class decalred inside managed c++ dll as
public class IPHelper
{
public:
static void CheckIP(LPWSTR pSocketName);
static void DebugMessage(const wchar_t *str, ...);
private:
static DWORD GetIPInformation(PSOCKET_RECORD &pInfo);
};
I compiled it successfully and add it as reference to my c# project.
I am able to use the namespace, however the class seems empty and I'm unable to call the functions inside it.
Any ideas?
That class is not managed, it is native. You need to call it a public ref class if you want to use it from managed code.
You're going to need to invoke it using the P/Invoke method. See this reference for more information.
As others have noted, that's a native C++ class. Assuming your project is CLR enabled, then you can easily write a simple C++ / CLI wrapper around it, which will allow you to use it in a managed context.
This is a quick overview of C++ / CLI which should get you started in the right direction.
That class seems to be a hybrid. You specified public class IPHelper, which is halfway what you want. You should specify it as public ref class IPHelper. However even so, it will still not interface well with managed classes, because of the parameter types it receives. For instance a wchar_t is not the same as a System::String^ (managed C++ way to declare strings). Similarly a LPWSTR is also not the same as a System::String^. As a side note, it would be best for you to write some utility methods to convert between .NET System::Strings and wchar_t and other native strings that you will most likely need. This is an excellent article on MSDN on how to convert between all the various string types.
Now I don't know if you want to expose this class directly to C#, or have this class in turn wrapped by a better managed wrapper than what you have here. But anyway you do it, the Managed C++ class's methods have to take .NET types in order to be directly used in C# code.
So, I have an executable file that was made with C#, I don't have its source code but I have disassembled it with IDA, and it gave me a lot of object oriented assembly.
I've made an .exe file that injects a .dll into another .exe, and I've injected this new C++ DLL into the C# .exe, with no problems, the DLLMain is called and so...
But when I inject this DLL into a normal .exe file made with C++, I can call a function in the .exe with its memory address which I can take on IDA.
The problem is, that object oriented assembly doesn't have addresses on its function, even with the function names being disassembled.
So, is there any way I can call this function with my injected DLL on the C# .exe file?
If possible, is there a way I can use the namespace declared in the C# .exe file and all its functions and variables, even being private?
Sample disassembled code:
.namespace MyCSharpApp
{
.class public auto ansi Test extends [mscorlib]System.Object
{
.field public value class [Microsoft.Xna.Framework]Microsoft.Xna.Framework.Vector2 pos
.field public int32 foo
....
You are trying to do something tricky and I'm not perfectly clear on what it is. From your description you have at least four things:
Managed EXE
Managed DLL
Unmanaged EXE
Unmanaged DLL
some of which you have control over (i.e. source code for), and some of which don't.
You want to use a process you call "injecting" to change a module you don't have control over to call a module you do have control over. In order to do this you are using a tool that requires you to have an unmanaged entry point in the address space of the process.
If you are getting what you want with unmanaged modules, then all you need to do is write a new mixed-mode module (over which you obviously have control) to call the managed DLL that you don't control. Now you effective have an unmanaged DLL (for export purposes) and the problem of it being managed has gone away.
To call managed code from your new unmanaged wrapper module, you can use the techniques described in this introductory article:
An Overview of Managed/Unmanaged Code Interoperability
Basically you need a C++/CLI project that references your black-box managed DLL and calls it and exports an unmanaged entry point that you can "take the address of" for your injection. Searching will find you a whole lot more ideas.
Finally, can you call private methods in the managed DLL (over which you have no control) using this method? No, not directly. However, its a managed DLL so it must have some public entry points to have ever been useful to anybody and you can call those. If that's not enough, you can use reflection from C++/CLI to call private methods and access private members.
You'll need to use the unmanaged hosting/debugging APIs. If you could inject a managed DLL, this would be much easier, you could just use Reflection.
I am attempting to write a DLL using the C# .NET Framework 2.0. Everything compiles okay, but when I try to access the DLL from my application, it fails when attempting to get the procedure address. So, I oped the DLL in Dependency Walker, and all of my public functions are missing!
My DLL, so far, is fairly straightforward:
namespace MyDll_Namespace
{
public class MyDllClass
{
public static int Func1( /* params */ ) { /* ... */ }
public static int Func2( /* params */ ) { /* ... */ }
public static int Func3( /* params */ ) { /* ... */ }
public static int Func4( /* params */ ) { /* ... */ }
}
}
There's not much else, just a few constants and delegates defined inside the class, as well as outside the class in the namespace. Any thoughts or suggestions would be much appreciated. Thanks.
Dependency walker is for win32 DLLs (which is native code), not .NET assemblies (which is managed code). It won't find methods in an arbitrary class (even if they are static). If you need to call managed code from native code, there are ways of doing that, but it's not pretty.
If you want to use your dll from managed code, it's a lot easier. Check out System.Assembly and Activator.
An example of this:
var assembly = Assembly.LoadFile(#"\path\to\your.dll");
var mydllclass_type = assembly.GetType("MyDllClass");
var instance = Activator.CreateInstance(mydllclass_type);
The instance will be an object. To call the methods, you need to use reflection, because the interface is not known at compile-time.
If you are creating a plugin system, the best way is to have a common interface or abstract base for all plugins, and have that referenced by your program. Those third parties who implement a plugin, will also reference this contract. In this case, the last line changes a bit:
var instance = (IMyDllClass)Activator.CreateInstance(mydllclass_type);
Now you can use the methods like in a regularly constructed object.
Part of the problem here is that dependency walker is a tool for native applications. It doesn't understand managed code and hence won't display any of the managed types + methods that you've defined.
I'm confused by this line in your question
when I try to access the DLL from my application, it fails when attempting to get the procedure address
This sounds a bit like an error I would see in a native application, not a managed one. Are you trying to access the C# code from a native application? If so this can only be done via COM magic and not via direct calling. Can you explain in more detail what is going on here?
Try .net Reflector to see exactly what's inside your built DLL (in order to make sure everything is the way it is supposed to).
Also make sure you're in release mode while building your DLL before referencing it... I don't know if it's going to change anything, but it worths the try =)
You need to add a reference to your dll and the runtime will automatically allow you to call your function. Here is a little tutorial on writing a .net class library.
I decided to write my DLLs in C++. However, here is a bunch of useful information I found for using managed code from unmanaged code:
Is it possible to use a DLL created using C# in an unmanaged VC++ application?
How do I call C++/CLI (.NET) DLLs from standard, unmanaged non-.NET applications?
Using managed code in an unmanaged application
Using Managed Components from Unmanaged Code
An Overview of Managed/Unmanaged Code Interoperability
Unmanaged Exports
Calling Managed .NET C# COM Objects from Unmanaged C++ Code
All-In-One Code Framework
CLR Hosting APIs
How To: Migrate to /clr
How to call a managed DLL from native Visual C++ code in Visual Studio.NET or in Visual Studio 2005