C#のプロジェクト名は「
Sample」として作成します。Cドライブ直下にプロジェクトを作成します。
C#のメソッドをC++で呼ぶにはC#側をCOM参照可能にすれば呼び出すことができます。
Class1.csは以下の内容となっています。
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Sample
{
// [ComVisible(true)]
public interface ICalc
{
int Add(int x, int y);
}
[ClassInterface(ClassInterfaceType.None)]
public class Calc : ICalc
{
public int Add(int x, int y)
{
return x + y;
}
}
}
► スポイラーを表示
CODE:
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Runtime.InteropServices
Public Interface ICalc
Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
End Interface
_
Public Class Calc
Inherits ICalc
Public Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function
End Class
ソリューションエクスプローラーから太字になっている「Sample」を右クリックして「プロパティ」を選びます。
「アプリケーション」の「アセンブリ情報」から「アセンブリをCOM参照可能にする」にチェックを入れ、「ビルドタブ」をクリックして「COM相互運用機能の登録」にチェックを入れます。
ビルドしてDllが生成されます。
「OLE+COM Object Viewer」でInterface欄に「ICalc」が表示されているかチェックします。ICalcを消すにはpublic interface と書かれた[ComVisible(true)]という行を[ComVisible(false)]に変えればOKです。
Visual Studio のVisual C++のプロジェクトから「Win32 コンソール」を選んでプロジェクトを作成します。このときATLにチェックを入れておきます。
タイプライブラリ(*.tlb)をプロジェクトに配置します。
Addを呼び出すには以下のプログラムを書いてビルドすれば呼び出せます。
CODE:
// CallCpp.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#import "Sample.tlb" no_namespace named_guids
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
{
CComPtr pObj;
HRESULT hr = pObj.CoCreateInstance(__uuidof(Calc));
ATLASSERT(hr == S_OK);
int ret = pObj->Add(1, 3);
printf("result %d\n", ret);
}
CoUninitialize();
return 0;
}
コンソール画面に
result 4
と表示されていたらC#のクラスライブラリは呼び出されています。ATL版ではCoInitializeとCoUninitializeの間に中括弧をつけているのはReleaseが自動的に呼ばれるようにしています。
中括弧なしでCoUninitializeを呼び出すと正しくReleaseが呼ばれない可能性があるのでメモリリークの可能性があるからです。
regasmとgacutilを使わない呼び出し方法については
マネージドDLLとの接続、ActiveX(COM)による接続、アンマネージドDLLとの接続というサイトをご覧ください。
さらにおまけでSample.tlhとSample.tliの中身です。
► スポイラーを表示
CODE:
//Sample.tlh
// Created by Microsoft (R) C/C++ Compiler Version 12.00.31101.0 (cefd5750).
//
// c:\callcpp\callcpp\release\sample.tlh
//
// C++ source equivalent of Win32 type library C:/CallCpp/CallCpp/Sample.tlb
// compiler-generated file created 09/02/15 at 20:02:41 - DO NOT EDIT!
#pragma once
#pragma pack(push, 8)
#include
//
// Forward references and typedefs
//
struct __declspec(uuid("2fb8ba48-8b0c-470e-890f-e9a9627358ee"))
/* LIBID */ __Sample;
struct __declspec(uuid("8ac7f5b7-0e9d-3fbb-8f4b-0784d3c80d15"))
/* dual interface */ ICalc;
struct /* coclass */ Calc;
//
// Smart pointer typedef declarations
//
_COM_SMARTPTR_TYPEDEF(ICalc, __uuidof(ICalc));
//
// Type library items
//
struct __declspec(uuid("8ac7f5b7-0e9d-3fbb-8f4b-0784d3c80d15"))
ICalc : IDispatch
{
//
// Wrapper methods for error-handling
//
long Add (
long x,
long y );
//
// Raw methods provided by interface
//
virtual HRESULT __stdcall raw_Add (
/*[in]*/ long x,
/*[in]*/ long y,
/*[out,retval]*/ long * pRetVal ) = 0;
};
struct __declspec(uuid("43fe739e-b446-3321-a352-4bb7deab1b16"))
Calc;
// interface _Object
// [ default ] interface ICalc
//
// Named GUID constants initializations
//
extern "C" const GUID __declspec(selectany) LIBID_Sample =
{0x2fb8ba48,0x8b0c,0x470e,{0x89,0x0f,0xe9,0xa9,0x62,0x73,0x58,0xee}};
extern "C" const GUID __declspec(selectany) IID_ICalc =
{0x8ac7f5b7,0x0e9d,0x3fbb,{0x8f,0x4b,0x07,0x84,0xd3,0xc8,0x0d,0x15}};
extern "C" const GUID __declspec(selectany) CLSID_Calc =
{0x43fe739e,0xb446,0x3321,{0xa3,0x52,0x4b,0xb7,0xde,0xab,0x1b,0x16}};
//
// Wrapper method implementations
//
#include "c:\callcpp\callcpp\release\sample.tli"
#pragma pack(pop)
//Sample.tli
// Created by Microsoft (R) C/C++ Compiler Version 12.00.31101.0 (cefd5750).
//
// c:\callcpp\callcpp\release\sample.tli
//
// Wrapper implementations for Win32 type library C:/CallCpp/CallCpp/Sample.tlb
// compiler-generated file created 09/02/15 at 20:02:41 - DO NOT EDIT!
#pragma once
//
// interface ICalc wrapper method implementations
//
inline long ICalc::Add ( long x, long y ) {
long _result = 0;
HRESULT _hr = raw_Add(x, y, &_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _result;
}