There is a WPF project on C # and C++ DLL implementing some complex computing, is it possible to connect this library to the C # project to create instances of C++ classes, and if so, what is required for this? If not difficult to explain in stages, I’m in this case a beginner.
Answer 1, Authority 100%
If you want to use the classes C++
, then the solution is approximately like this:
- Announce a class which will
Generic
class:
public abstract class cclassbase & lt; tnewdelegate, tdeleteedelegate & gt; :
IDisposable.
Where TNewDelegate: DELEGATE
Where TDeleteedelegate: Delegate
{
PROTECTED TNEWDELEGATE NEW;
PROTECTED TDELETEDEEGATE DELETE;
PROTECTED INTPTR THISPTR;
PROTECTED CCLASSBASE (TNEWDELEGATE NEWDELEGATE, TDELETEDEEGATE DELETEDEEGATE)
{
New = newdelegate;
Delete = deleteedelegate;
}
Public Bool IsDisposed
{
get;
PROTECTED SET;
}
PROTECTED ABSTRACT VOID DISPOSE (BOOL DISPOSABLE);
Public Void Dispose ()
{
DISPOSE (TRUE);
Gc.SuppressFinalize (this);
}
~ CCLASSBASE ()
{
DISPOSE (FALSE);
}
}
- inheritance from this class, basic class, not
Generic
:
// delegate designer without parameters, you can define your own and inherited from generic class
[UnmanagedFunctionPointer (CallingConvention.Thiscall)]
Public Delegate Void NewDelegate (Ref Intptr Thisptr);
[UnmanagedFunctionPointer (CallingConvention.Thiscall)]
Public DELEGATE Void Deleteedelegate (Ref Intptr Thisptr);
Public Class CCLASSBASE:
CCLASSBASE & LT; NewDelegate, Deleteedelegate & GT;
{
PROTECTED CCLASSBASE (NewDelegate Newdelegate, Deleteedelegate Deleteedelegate)
: Base (Newdelegate, Deleteedelegate)
{
New (Ref thisptr);
}
PROTECTED OVERRIDE VOID DISPOSE (BOOL DISPOSABLE)
{
if (isdisposed)
{
Return;
}
Delete (Ref thisptr);
if (disposable)
{
Thisptr = intptr.zero;
NEW = NULL;
Delete = null;
}
IsDisposed = True;
}
}
- Description of unmanaged (exported class) class:
In my case uncontrollable class declared as:
struct mi_core_api engine: public :: window_container
{
Public:
:: Lresult On_Message (:: Hwnd Hwnd, :: Uint MSG, :: WPARAM W_PARAM, :: LPARAM L_PARAM) Override;
BOOL PROCESS_MESSAGES () OVERRIDE;
BOOL INITIALIZE (:: hinstance app_instance, :: int32_t width, :: int32_t height, wchar_t const * application_name);
};
Accordingly, I defined the managed class as:
Public Class Engine:
CCLASSBASE.
{
[DLLIMPORT ("MI_CORE.DLL",
CallingConvention = CallingConvention.Thiscall,
Entrypoint = "?? 0Engine @@ Qae @ xz")]
Private Static Extern Void Enginenew (Ref Intptr Thisptr);
[DLLIMPORT ("MI_CORE.DLL",
CallingConvention = CallingConvention.Thiscall,
Entrypoint = "?? 1Engine @@ uae @ xz")]
Private Static Extern Void EnginedElete (Ref Intptr PTR);
[DLLIMPORT ("MI_CORE.DLL",
CallingConvention = CallingConvention.Thiscall,
Entrypoint = "? Initialize @ Engine @@ Qae_npauhinstance __ @@ hhpb_w @ z")]
Private Static Extern Bool Engineinitialize (Ref Intptr Thisptr, Intptr ApplicationInstance, Int Width, Int Height,
[Marshalas (UNMANAGEDTYPE.LPWSTR)] String ApplicationName);
[DLLIMPORT ("MI_CORE.DLL",
CallingConvention = CallingConvention.Thiscall,
Entrypoint = "? Process_Messages @ Engine @@ uae_nxz")]
Private Static Extern Bool EngineProcessMessages (Ref Intptr Thisptr);
Public Engine ():
Base (Enginenew, EnginedElete)
{
GC.KEEPALIVE (THIS);
}
Public Bool ProcessMessages ()
{
Return EngineProcessMessages (Ref Thisptr);
}
Public Bool Initialize (Int Width, Int Height, String ApplicationName)
{
ProcessModule ProcessModule = Process.GetcurrentProcess (). Mainmodule;
if (ProcessModule == NULL)
{
RETURN FALSE;
}
Intptr ApplicationInstance = ProcessModule.BaseAddress;
Return EngineInitialize (Ref Thisptr, ApplicationInstance, Width, Height, ApplicationName);
}
}
Well, start:
internal static class program
{
Public Static Int Main (String [] Args)
{
Using (Engine Engine = New Engine ())
{
if (! engine.initialize (1280, 720, "Some Application Name"))
{
Return 1;
}
While (Engine.ProcessMessages ())
{
}
}
Return 0;
}
}
Result: