.Net platform invoke の acquaintance

Foreword

The work process will inevitably encounter mixed programming, and now we want to talk about c ++ and C # programming language. To call C # C ++ libraries present available mainly in two ways: Com technology and platform invoke (P / Invoke). Now we want to talk about P / Invoke technology.

First, the platform calls

 Use technology platform calls can call the DLL in managed code unmanaged function (Dll) implemented, such as dll Win32 Dll and C / C ++ created. See here, some friends should have doubts - we can use in what situations

Technology platform invoke to call a dynamic link library unmanaged function?

.Net API encapsulates some of the system calls for us, my general operations we are accessing the system, but not comprehensive, we also need their own API to access the system.

Some programs, such as screenshots, substrate treatment, using C / C ++ has a great advantage, in particular, and other company's products when docking.

Managed code is not as efficient unmanaged code, in order to improve efficiency, may also be considered at this time managed code C library function call.

 Platform Invoke step

(1) Obtained information unmanaged function, the name of the dll, call the unmanaged function name and other information

(2). Declared unmanaged functions in managed code, calling the platform and the additional properties required

(3) In the second step directly call managed code declared in a managed function

The calling process platform calls

(1) Find a DLL that contains the function (function declarations of local identity when needed dllimport)

(2) to find the DLL loaded into memory.

(3) function to find the address in memory to which the parameters and pushed onto the stack, to marshal data required. CLR only when the first call, only to find and load the DLL, and the address lookup function in memory. When the function is called once after CLR address will be cached function, this mechanism can improve the efficiency CLR platform calls. Prior to the application domain is unloaded, have been found DLL in memory.

(4) perform unmanaged functions.

Construction of two, C / C ++ libraries

Note: C # is not calling c ++ class directly, we can write a c ++ class, and then packaged into a C function by C / C ++ way, foreign exposure. For simplicity, only the following C function.

1, we choose New Project (C ++, dynamic link libraries)

 

 

 2, do not select an empty project, because there may be other dependencies

 

 

 3, delete the sample code that comes, we add its own interface (attach a callback method)

#ifdef ADDDLL_EXPORTS
#define ADDDLL_API __declspec(dllexport)
#else
#define ADDDLL_API __declspec(dllimport)
#endif

typedef void(__stdcall * RecvDataCallback) (unsigned char* pData, int iDataSize, int iMsgType, long lContext);

long mCallBackFunction=NULL;

EXTERN_C ADDDLL_API int add(int a,int b);

EXTERN_C ADDDLL_API bool MLogin(long lInstance,ULONG pServerIP,int iConferenceNo,long pCallBackFunction,long lContext);

EXTERN_C ADDDLL_API bool MLogout(long lInstance);

EXTERN_C ADDDLL_API bool MSendData(long lInstance,unsigned char* pData,int iDataSize,int iMsgType);

void logPrintf(const char* str);

cpp file to achieve

// AddDll.cpp: custom DLL application of export functions.
//
 
#include " the stdafx.h " 
#include " AddDll.h " 


int the Add ( int A, int B) 
{ 
    return A + B; 
} 

ADDDLL_API BOOL MLogin ( Long lInstance, ULONG pServerIP, int iConferenceNo, Long pCallBackFunction, Long lContext ) 
{ 
    STD :: String strlog = " log from Login: \ R & lt \ n- " ; 
    strlog + ="lInstance:" + std::to_string(lInstance);
    strLog += " pServerIP:"+ std::to_string(pServerIP);
    strLog += " iConferenceNo:" + std::to_string(pServerIP);
    strLog += " pCallBackFunction:" + std::to_string(pCallBackFunction);
    strLog += " lContext:" + std::to_string(lContext);
    strLog += "\r\n" ;
    logPrintf(strLog.c_str ());

    mCallBackFunction = pCallBackFunction;

    return true;
}

ADDDLL_API bool MLogout(long lInstance)
{
    std::string strLog = "log from logout:\r\n";
    strLog += "lInstance:" + std::to_string(lInstance);
    strLog += "\r\n";
    logPrintf(strLog.c_str());
    return true;
}

ADDDLL_API bool MSendData(long lInstance, unsigned char * pData, int iDataSize, int iMsgType)
{
    std::string strLog = "log from sendData:\r\n";
    strLog += "lInstance:" + std::to_string(lInstance);
    strLog += " pData:" + std::string((const char *)pData);
    strLog += " iDataSize:" + std::to_string(iDataSize);
    strLog += " iMsgType:" + std::to_string(iMsgType);
    strLog += "\r\n";
    logPrintf(strLog.c_str());

    ( *(RecvDataCallback) mCallBackFunction)((unsigned char*) pData, strlen((const char *)pData), iMsgType, 0);

    return true;
}

void logPrintf(const char * str)
{
    FILE* fp = fopen("D:\\log.txt", "a+");
    if (fp)
    {
        fprintf(fp, str);
        fclose(fp);
    }
}
View Code

Generation to

4. It should be noted, do not check the empty project, since there may be dependencies, if it is to call C ++, where you can select an empty project

Be sure not to forget Export logo

extern "C" __declspec (dllexport) 
see: point I was

three, C # side call
  /// <summary>
    /// 注意:需要类中声明,方法中new,避免被回收
    /// </summary>
    /// <param name="pData"></param>
    /// <param name="iDataSize"></param>
    /// <param name="iMsgType"></param>
    /// <param name="lContext"></param>
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate  void RecvDataCallback(IntPtr pData,int iDataSize, int iSendMsgType, int iCallBackMsgType, long lContext);

    staticpublic
    {CRelayclassstaticpublic  
          Int32 lInstance = 0;

        [DllImport("RelayDllR.DLL", EntryPoint = "CreateInstance", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 CreateInstance();

        [DllImport("RelayDllR.DLL", EntryPoint = "DestroyInstance", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern void DestroyInstance(Int32 lInstance);

        [DllImport("RelayDllR.DLL", EntryPoint = "Login", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Login(Int32 lInstance, UInt32 pServerIP, Int32 iConferenceNo,/*RecvDataCallback*/Int32 pCallBackFunction, Int32 lContext);

        [DllImport("RelayDllR.DLL", EntryPoint = "Logout",SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Logout(Int32 lInstance);

        [DllImport("RelayDllR.DLL", EntryPoint = "SendData", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool SendData(Int32 lInstance, [MarshalAs(UnmanagedType.LPArray)] byte[] pData, Int32 iDataSize, Int32 iMsgType);
 

Note: The callback statement can not be less good [UnmanagedFunctionPointer (CallingConvention.Cdecl)], or it may only be a limited number of calls after the release of the platform, at the call should be initialized (to avoid being recovered GC) in the class declaration, methods.

 

 

Guess you like

Origin www.cnblogs.com/xietianjiao/p/11599477.html