How C + + invokes DLL developed by C #

Source: Internet
Author: User
Tags response code

Preface

This article describes how a C + + DLL instance is invoked by C # development.

Objective

A program written in C + + is unmanaged code, and a program written in C # is managed code. While managed code offers many advantages that other development platforms do not, the CLR provides mechanisms that allow both managed and unmanaged code to be included in the application because of the many uses of unmanaged code written by the previous system and historical versions. Specifically divided into the following three kinds:

    1. managed code can invoke unmanaged functions in the DLL. functions in the DLL are called through the P/invoke (Platform invoke) mechanism, such as Kernel32.dll.
    2. managed code can use an existing COM component (server). Many companies have implemented a large number of unmanaged COM components. Using a type library from these components, you can create a managed assembly to describe the COM component. Managed code can access types in a managed assembly as if it were any other type.
    3. Managed types (servers) can be used by unmanaged code. Many existing unmanaged code requires the COM component to be provided to ensure that the code works correctly. Using managed code makes it easier to implement these components, avoiding all code having to deal with reference counts and interfaces. For example, C + + invokes DLL developed by C #.

Some of the above text is from the CLR via C #, which is a bit more difficult to understand. There is the experience of working with DLLs developed through C + + calling C #, which is the 3rd above. So I want to take this article to record the development of the steps and ideas. The subsequent time to the above 1, 2 points to fill up, forming a series of articles.

Body 1, writing DLLs in C #

The DLL simply implements two functions: string concatenation and the addition of two numbers. First create the method interface: Add and join. The code is as follows:

[Guid ("254d1fbc-416b-422f-ae39-c923e8803396")]    Public InterfaceIcalc {[DispID (1)]        BOOLADD (stringAstringB out intc); [DispID (2)]        voidJoin (stringAstringB out stringc); }

To provide a more comprehensive description of the invocation method type, the Add method return value is specifically defined as type bool, and the result is output by output parameter, int type;

The Join method has no return value (Type void), and the result is output from the output parameter, which is of type string.

where the DispID attribute and the GUID attribute are required. DispID are numbered sequentially. The GUID creation step for the tool--Create guid--> Select item 5th, copy (for VS2013) as shown:

Next, create the Calc class that inherits the Icalc interface, implementing the Add and join methods, as shown in the code below. You also need to create a GUID, as in the previous step.

[Guid ("f963b111-39fa-499d-9172-6102c79bb6e5")][classinterface (classinterfacetype.none)] Public classCalc:icalc { Public BOOLADD (stringAstringB out intc) {intint_a; intInt_b; if(! Int32.TryParse (A, outint_a)) {C=0; return false; }            if(! Int32.TryParse (b, outint_b)) {C=0; return false; } C= Int_a +Int_b; return true; }         Public voidJoin (stringAstringB out stringc) {c= A +b; return ; }    }

You will also need to set the "Make assembly COM Visible" and "Register for COM Interop"

The "Make assembly COM Visible" step is: Project Properties--"Application" Item--"assembly information"--tick "make assembly COM visible" as shown in:

The "Register for COM Interop" setting is: Project Properties--"Generate" Item and tick "Register for COM Interop" as shown in:

Note: This operation requires system administrator privileges, run as "Administrator" when starting VS, otherwise the Access denied error to registry key XXX Occurs when the solution is built.

After the solution is built, a DLL and TLB two files are generated. This completes the C # end of the work.

The next step is to generate a registry file from Regasm.exe for the consumer to register the DLL as a COM component.

2. Registering DLLs as COM components

At the time of the native development, it was checked to check the "Register for COM Interop" option, so when the solution was built, the DLL was registered as a COM component in this machine, so the runtime does not need to register again.

However, if you are running on another machine, you need to register the DLL as a COM component before you can use it. Here we generate the registry file through Regasm.exe for the consumer to register the DLL as a COM component (in fact, the GUID is imported into the registry).

The script file is as follows:

regasm E:\ Blog Park \unmanagecodecallmanagecode\calcclass\calcclass\bin\debug\calcclass.dllregasm e:\ Blog Park \ Unmanagecodecallmanagecode\calcclass\calcclass\bin\debug\calcclass.dll/tlb:CalcClass.tlbregasm e:\ Blog Park \ Unmanagecodecallmanagecode\calcclass\calcclass\bin\debug\calcclass.dll/regfile:calcclass.reg

Note The Regasm.exe version used is best aligned with the. NET framework version used by the development DLL.

Run the script to generate the Calcclass.reg file. Run the file on another machine to register the COM component for normal use.

The next question is how to encapsulate it as a COM component.

3. Encapsulating a DLL as a COM component

Create a new workspace, select Win32 dynamic-link Library, type simple DLL project.

Copy the above generated DLL and TLB two files to the workspace file path.

Add the following two lines of code to the DLL under the StdAfx.h header file: (The content needs to be changed based on the TLB file name and namespace)

" calcclass.tlb " using namespace Calcclass;

Add the following method declaration in the CPP file (declared as an external function of the C-compile connection), or you can create a header file to include.

extern " C "_declspec (dllexport) BOOL Add (Char* A,char* b,long* c); extern " C "_declspec (dllexport)void Join (Char* A,char* b,char* c);

Two ways to implement a declaration:

BOOL Add (CharBChar* B,Long*c)    {CoInitialize (NULL); Calcclass::icalcptr calcptr (__uuidof (Calc));//gets the GUID associated with the CalcVARIANT_BOOL ret = calcptr->Add (_bstr_t (a), _bstr_t (b), c); Calcptr-Release ();       CoUninitialize (); if(ret = =-1 )        return 1; Else        returnret;}voidJoin (CharBChar* B,Char*c)    {CoInitialize (NULL); Calcclass::icalcptr calcptr (__uuidof (Calc));//gets the GUID associated with the CalcBSTR temp; Calcptr->join (_bstr_t (a), _bstr_t (b),&temp);    strcpy (c, _com_util::convertbstrtostring (temp)); Calcptr-Release ();   CoUninitialize (); }

Here's a two-point explanation:

1, for the Variant_bool type to do a brief introduction:-1 means that true,0 is false. (This really overturns our conventional understanding of the bool value.)

2, C # when the out parameter is converted to C + + must pass pointer variable, that is, the parameter must be taken to refer to the operation, which is the essence of the output parameters. (Can be referred to by the TLB file reference, or after the build reference view Tli or TLH file)

Successful compilation completes the task of encapsulating the DLL as a COM component. At this point, C + + can invoke a DLL written in C #. A demo example of the call is shown below.

4. Call Demo sample

New workspace, select Win32 exe, type dialog box. The design interface is as follows, adding button events onaddbtn and ONJOINBTN

Declare the method with the following code:

typedef BOOL (* Add) (Char* A,char* b,long*void (* Join) (Char* A, Char* b,char* c);

The Onaddbtn event response code is as follows:

voidccalccomdemodlg::onaddbtn () {//Todo:add your control notification handler code hereBOOL ret; Longresult; Chara[255]; Charb[255];    CString str_a;            CString Str_b; GetDlgItem (IDC_EDIT1)-GetWindowText (str_a); GetDlgItem (IDC_EDIT2)-GetWindowText (Str_b);    strcpy (a,str_a);    strcpy (B,str_b);    HINSTANCE Calc; Calc= LoadLibrary (TEXT ("CalcCom.dll")); if(NULL = =Calc) {MessageBox ("cant ' t find dll"); return; } Add _add= (ADD):: GetProcAddress (Calc,"ADD"); if(NULL = =_add) {MessageBox ("cant ' t find function"); return; }        Else{ret= _add (a,b,&result);            CString boxmsg; Boxmsg.format ("Reslut:%d\nmessage:%ld\n", Ret,result);        MessageBox (BOXMSG); }}

The Onjoinbtn event response code is as follows:

voidccalccomdemodlg::onjoinbtn () {//Todo:add your control notification handler code here    Chara[255]; Charb[255];    CString str_a;            CString Str_b; GetDlgItem (IDC_EDIT1)-GetWindowText (str_a); GetDlgItem (IDC_EDIT2)-GetWindowText (Str_b);    strcpy (a,str_a);    strcpy (B,str_b); Charresult[255];    HINSTANCE Calc; Calc= LoadLibrary (TEXT ("CalcCom.dll")); if(NULL = =Calc) {MessageBox ("cant ' t find dll"); return; } Join _join= (Join):: GetProcAddress (Calc,"Join"); if(NULL = =_join) {MessageBox ("cant ' t find function"); return; }        Else{_join (a,b,result);            CString boxmsg; Boxmsg.format ("message:%s\n", result);        MessageBox (BOXMSG); }}

Here is the LoadLibrary (TEXT ("CalcCom.dll")), which defaults to the DLL under EXE execution path. So the generated COM component DLL is copied to the EXE execution path after the compilation is complete. Of course, you can also specify the path to the DLL directly.

Run the program to verify that the DLL written in C # is successfully invoked. As shown in.

How C + + invokes DLL developed by C #

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.