P-Invoke in .net core with Linux - pinvoke

Is there way to implement P/Invoke (dllimport) in .NET Core on Linux ?
Example :
I have C++ MyLib.dll compiled with .net framework.
If it is possible to use like this or it's not support to call native win api with linux using .net-core ?
[DllImport("MyLib.dll", CallingConvention = CallingConvention.StdCall)]
internal static extern long NativeMethod();

PInvoke is certainly supported (that is how all of the code that interfaces with the OS works), but not in the specific case you listed. You cannot PInvoke to a win32 binary on Linux, unless you have somehow built a function-compatible version of it for Linux yourself. More realistically, you need to find a Linux function from some other system binary which exposes similar functionality, and then use that instead.

Even dlls exists only in Windows OS, you can import and use some linux APIs using PInvoke in .NET Core.
Samples:
[DllImport("libc")]
static extern int read(int handle, byte[] buf, int n);
[DllImport("libc.so.6")]
private static extern int getpid();
[DllImport("libgtk-x11-2.0.so.0")]
static extern IntPtr gtk_message_dialog_new(IntPtr parent_window, DialogFlags flags, MessageType type, ButtonsType bt, string msg, IntPtr args);
Please see https://developers.redhat.com/blog/2016/09/14/pinvoke-in-net-core-rhel/
https://gist.github.com/martinwoodward/f5b195aa53b4ed52cabaf701486baa79

Related

What .NET type marshalls to COM UINT?

In C# I am declaring an interface, which will be exposed to COM for use by C++. Our spec says one integer parameter should be [in]UINT uiVal. I'm using int in C# and it is being exposed as long.
It's not a big deal, but how can I force it to marshall to UINT rather than long? Some specific .Net type, or do I need to add attributes to the C# parameter somehow?
UINT is a type alias from the Windows SDK, you will never get it out of a type library. Tooling that translates type libraries, like the #import directive you are using, pick native C types. History plays a role, COM was originally designed for the 16-bit version of Windows. When long was important to declare a 32-bit integer.
Closest you can get is uint in the C# declaration, it will be translated to unsigned long in your C++ code. Which is fine, it is still a 32-bit type, Microsoft chose the LLP64 data model for 64-bit code. They did not have much of a choice. Unlike the LP64 model chosen in *nix. They did not have much of a choice either, the Y2K38 disaster is approaching fast :)

Generic List in C# DLL cannot be accessed from CLI

Want to preface this by pointing out I am new to C++/CLI
We have one solution with an unmanaged C++ application project(We'll call "Application") and a C# .net remoting project which builds to a DLL(We'll call "Remoting"), and a CLI project for interfacing between the two(We'll call "Bridge").
Everything seems to be working, we have an IMyEventHandler interface in Bridge which successfully receives events from Remoting and can call methods in Application.
#ifndef EVENTS_HANDLER_INTERFACE_H_INCLUDED
#include "EventsHandlerInterface.h"
#endif
#define DLLEXPORT __declspec(dllexport)
#ifdef __cplusplus
extern "C"
{
#endif
DLLEXPORT bool RegisterAppWithBridge(IMyEventsHandler * aHandler);
DLLEXPORT void PostEventToServer(AppToServerEvent eventType);
DLLEXPORT void PollEventsFromServer();
#ifdef __cplusplus
}
#endif
In Bridge implementation we have a method for handling an event and depending on which event type it is, we will call a different method for handling that exact type:
void Bridge::OnReceiveServerEvent(IMyEvent^ aEvent)
{
// Determine event type
...
Handle_SpecificEventType();
}
This all is working fine so far. Once we call the handler for a known type of event, we can directly cast to it from the generic interface type. And this is where we start to see the issue. All these event types are defined in another DLL generated from C#. Simple events that have just ints or strings work just fine, but we have this SpecificEventType which contains a list of other types(We'll call "AnotherType") all defined in another DLL. All required DLL's have been added as references, and I am able to gcnew a AnotherType without it complaining.
However, once I try to get AnotherType element out of the list, we see the build error: "C2526 'System::Collections::Generic::List::GetEnumerator' C linkage function cannot return C++ class"
void Bridge::Handle_SpecificEventType(IMyEvent ^evt)
{
SpecificEventType ^e = (SpecificEventType ^)evt;
// We can pull the list itself, but accessing elements gives error
System::Collections::Generic:List<AnotherType ^> ^lst = e->ThatList;
// These all cause error
array<AnotherType ^> ^arr = lst->ToArray();
AnotherType ^singleElement = lst[0];
for each(AnotherType ^loopElement in lst){}
}
To clarify why we're doing this, we are trying to take managed events defined in a C# DLL and sent through .net remoting from a newer C# server, and "translate" them for an older unmanaged C++ application. So the end goal is to create a copy of the C# type "SpecificEventType" and translate it to unmanaged "SpecificEventType_Unmanaged" and just make a call to the application with that data:
// Declared in Bridge.h and gets assigned from DLLEXPORT RegisterGameWithBridge method.
IMyEventsHandler *iApplicationEventHandler;
// Bridge.cpp
void Bridge::Handle_SpecificEventType(IMyEvent ^evt)
{
... Convert SpecificEventType to SpecificEventType_Unmanaged
iApplicationEventHandler->Handle_SpecificEvent(eventUnmanaged);
}
This messaging all seems to be working and setup correctly - but it really doesn't want to give us the elements from the generic list - preventing us from pulling the data and building an unmanaged version of the event to send down to the application.
I hope I have explained this well, again I am new to CLI and haven't had to touch C++ for some years now - so let me know if any additional details are needed.
Thanks in advance for any assistance.
Turns out the issue was because all the methods in Bridge implementation were still inside of an extern "C" block. So much time lost - such a simple issue.

How to implement Unity like internal call with mono

C# side code
[WrapperlessIcall]
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void INTERNAL_set_rotation(ref Quaternion value);
How to expose this method from C++ to mono
Thanks.
You need to call mono_add_internal_call:
mono_add_internal_call ("YourClass::INTERNAL_set_rotation", yourclass_INTERNAL_set_rotation);
There is some documentation here: http://www.mono-project.com/Embedding_Mono#Exposing_C_code_to_the_CIL_universe
And here is a code sample: https://github.com/mono/moon/blob/8d8ece884382d653d215b0da5bf633079566d816/src/deployment.cpp#L579

How to manage .Net's RCW COM object creation paramets (namely requested interface)?

I'm using an external native COM component in my C# .NET application.
This COM DLL doesn't have a type library, so I had to write the interop code myself, and having include/idl files I did it like TlbImp does.
But the worst thing is that the object creation fails with:
Creating an instance of the COM component with CLSID {40700425-0080-11D2-851F-00C04FC21759} from the IClassFactory failed due to the following error: 80040111
The class is finally created if I use the native CoCreateInstance and specify class_id and one of the implemented interface IIDs.
As it turned out the problem lies in that the COM object's IClassFactory::CreateInstance doesn't support IID_IUnknown passed as the riid parameter, and therefore returns CLASS_E_CLASSNOTAVAILABLE (I identified it with disassembler and debugger). The component is MS SQL VDI.
Is there any way to force the .NET RCW to pass a different interface ID into the CreateInstance method rather than IID_IUnknown?
I searched the net a lot, but didn't find a solution for this.
As a workaround I'm using C++/CLI now to create the object, requesting the proper interface instead of IID_IUnknown for this purpose now; but I would like to have code in C#, because C++/CLI requires me to build a different DLL for each platform.
Thanks
I repro. Brr, painful. You could pinvoke CoCreateInstance:
[return: MarshalAs(UnmanagedType.Interface)]
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
public static extern object CoCreateInstance(ref Guid clsid,
[MarshalAs(UnmanagedType.Interface)] object punkOuter, int context, ref Guid iid);

export typedefs in .NET dlls

I've written a wrapper for a C++ dll in C++/CLI. Inside the wrapper, I made some typedefs. Is there a way to export these names as .NET classes?
Background: the typedef'd classes are some templates. For these templates to work, you need a managed and a native parameter (this is part of the translation). This is impossible for the client of the wrapper to program / know. That's why he needs the different aliases for the used versions of the template.
I exchanged the typedefs with some new class definitions that derive from the template. This should work.
I do not have too much information but typedefing should work only on Clr types. Generic classes, maybe but template classes can not ne typedefed. Also among native types, only the ones that are common (the word "common" may not be correct here.) to .net i.e. double, int, char, Char* (not char*) etc.
This code works and introduces a "new" type to clr.
namespace example
{
#ifdef _WIN64
typedef sizeT UInt64
#else
typedef sizeT UInt32
#endif
}
Now you have size_t of .Net, whose size depends on platform.