1. 程式人生 > >C#生成com元件形式的dll供C++呼叫

C#生成com元件形式的dll供C++呼叫

①建立C#類庫(ClassLibrary)、設定AssemblyInfo.cs中的[assembly: ComVisible(true)]預設是false、或者在介面和類之前新增設定為true
    [ComVisible(true)]
    [Guid("E709D3B9-18E8-4189-B1E0-49F72DD5A74C")]

    public interface CombineToolInterface{

       [DispId(1)]
       bool CalcuHeight(Object files, ref float fHeight)

利用VS工具中的建立GUID生成GUID

②定義介面其中每個介面對應一個[DispId(1)] id必須唯一。

③具體實現

    [ComVisible(true)]
    [Guid("C76A4C63-46DE-4D3A-8DD7-00E71B42D9AA")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("PDFCombine.CombineToolInterface")]

    public class CombineTool : CombineToolInterface{

      bool CalcuHeight(Object files, ref float fHeight){

              List<string> arrFile = new List<string>((string[])files);

              return true;}

④預設情況下會生成.tlh和.dll檔案,然後使用VS類嚮導新增類選擇 MFC Class From TypLib..如下圖:

有.h和dll檔案VC就可以使用了。

注:若C#引數需要陣列,則可以定義為Object,C++對應的是VARINT
eg. BOOL CalcuHeightWidth(VARIANT& files, float * fHeight) {
        BOOL result;
        static BYTE parms[] = VTS_VARIANT VTS_PR4 ;
       return result;
}

在COM中傳遞陣列需要SAFEARRY,但是SAFEARRY需要使用VARIANT包裝一下,如下:
    VARIANT arryVar;
    VariantInit( &arryVar );
    arryVar.vt = VT_ARRAY | VT_BSTR;
    SAFEARRAY* pSa = SafeArrayCreateVector(VT_BSTR, 0, vecTmpFiles.size());

    BSTR* bFile = new BSTR[vecTmpFiles.size()];
    for (int i = 0; i < vecTmpFiles.size(); ++i)
    {
        bFile[i] = SysAllocString(vecTmpFiles.at(i));
        SafeArrayPutElement(pSa,(long*)&i, bFile[i]);
    }

    SafeArrayAccessData(pSa, (void**)&bFile);
    arryVar.parray = pSa;
    SafeArrayUnaccessData(pSa);
    SafeArrayDestroy(pSa); //會自動釋放BSTR* bFile陣列,無需再釋放bFile,否則重複釋放。