- PR -

C#でアンマネージドC++クラスを使う

1
投稿者投稿内容
KAGAMI
会議室デビュー日: 2007/12/17
投稿数: 5
投稿日時: 2007-12-17 13:07

既に作成済みのアンマネージドC++のコードをVS2003C++とVS2005C#で共用したいと考えています。

VS2003C++にて、アンマネージドのクラス、それをラップするマネージドのクラスをDLL化しておけば、
VS2005C#でもDLLを参照すれば共用できると考えて、試しているのですがうまくいきません。

詳細ですが

VS2003のC++にて、
アンマネージドのC++クラスとそれをラップしたマネージドのC++クラスが含まれているDLLを作成しました。
コードとしては、ネットですぐに見つかるアンマネージドラップのサンプルそのままです。

試しに、VS2003C++にて別のプロジェクトを作成し、DLLを参照してマネージドのクラスを使ってみたら、
ラップのクラスとして、期待通りに動きました。

今度はVS2005のC#にてそのDLLを参照してマネージドのクラスを使ってみると、
アンマネージドのクラスを使用する部分(コンストラクタ)でSystem.StackOverflowExceptionが発生し、落ちてしまいます。

VS2003で参照した時は動いていたので、単純なコード記述ミスでStackOverflowExceptionが出ている訳ではないと思うのですが。


構造として間違ったものになっているのではないか?と行き詰まり、ご意見を頂きたく、投稿してみました。

宜しくお願いします。

囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-12-17 13:23
どんなコードが見せていただかないと分かりません。
_________________
囚人のジレンマな日々
KAGAMI
会議室デビュー日: 2007/12/17
投稿数: 5
投稿日時: 2007-12-17 13:49

コードは以下のようになっております。

下記のmyLib.cpp、myLib.h、VS2003C++でDLLを作成しました。

---<myLib.h>----

#pragma once

#using <mscorlib.dll>

class __declspec(dllexport) MyClass {
private:

int a,b,c; //プライベート変数

public:
MyClass(); //コンストラクタ
~MyClass(); //ディストラクタ
void SetData(int,int); //プライベート変数に値を設定
int GetData(); //プライベート変数Cの値を取得
void Calc(); //単に内部で c=a+bを計算する
};

namespace testSpace
{
public __gc class MClass
{
public:
MClass()
{
m_pC = new MyClass();
}
~MClass() { delete this->m_pC; }
void SetData_f(int a,int b) {this->m_pC->SetData(a,b);}
int GetData_f(){return this->m_pC->GetData();}
void Calc_f(){this->m_pC->Calc();}

private:
MyClass * m_pC;
};
};

---<myLib.h ここまで>----



---<myLib.cpp>----

#include <windows.h>
#include "myLib.h"

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason) {
case DLL_PROCESS_ATTACH:
//初期処理
break;
case DLL_PROCESS_DETACH:
//終了処理
break;
}

return 1; // OK
}

MyClass::MyClass()
{
a = b = c = 0;
}


MyClass::~MyClass()
{
}


void MyClass::SetData(int p1,int p2)
{
a=p1;
b = p2;
}

int MyClass::GetData()
{
return c;
}

void MyClass::Calc()
{
c = a+b;
}

---<myLib.cpp ここまで>----

そのDLLをVS2005C#にて参照し、

testSpace.MClass m = new testSpace.MClass();

このようにインスタンスを生成したところで、StackOverflowExceptionが発生します。

囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-12-17 14:19
m_pC = new MyClass();

ここの MyClass がどこのクラスを指しているんだって話だと思います。別の名前にしたらいかがでしょう。

あと、マネージ C++ の DLL に DllMain は必要ないと思いますが。アンマネージの DLL をエクスポートする気がないなら __declspec(dllexport) は必要ないですし(そもそもアンマネージC++クラスをエクスポートするのは一癖ありますが)。

更に言うと、VC++ 2003 で生成されるアセンブリは .NET1.1、VC#2005で生成されるアセンブリは .NET2.0が対象ですよね。まぁ動かない事はないと思いますが、どちらも 2.0 環境で動きますよ。

_________________
囚人のジレンマな日々
KAGAMI
会議室デビュー日: 2007/12/17
投稿数: 5
投稿日時: 2007-12-17 15:10

ご指摘有り難うございます。

区別がはっきりつくように、アンマネージドのクラス名を変えて、アンマネージドクラスのほうも違うnamespaceでくくりました。
__declspec(dllexport) 、DllMainも外しました。

それでも現象は変わりませんでした。


DLLを提供する先がまだVS2003C++で開発しているようなので、そこに合わせて作っておき、こちらはVS2005C#で引き込めばいいかな、という所からの出発です。

実現できていないので、合わせるという考え方がよくないのかな??など迷走しております。

囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-12-17 15:21
引用:

区別がはっきりつくように、アンマネージドのクラス名を変えて、アンマネージドクラスのほうも違うnamespaceでくくりました。
__declspec(dllexport) 、DllMainも外しました。


で、どんなコードになったんでしょうか。

_________________
囚人のジレンマな日々
KAGAMI
会議室デビュー日: 2007/12/17
投稿数: 5
投稿日時: 2007-12-17 15:33

ご指摘を元に、以下のようなコードに変更いたしました。

---<myLib.h>----

#pragma once

#using <mscorlib.dll>

namespace Unmanaged;
{
class UnmanagedClass {
private:

int a,b,c; //プライベート変数

public:
UnmanagedClass(); //コンストラクタ
~UnmanagedClass(); //ディストラクタ
void SetData(int,int); //プライベート変数に値を設定
int GetData(); //プライベート変数Cの値を取得
void Calc(); //単に内部で c=a+bを計算する
};
};

namespace testSpace
{
public __gc class MClass
{
public:
MClass()
{
m_pC = new Unmanaged::UnmanagedClass();
}
~MClass() { delete this->m_pC; }
void SetData_f(int a,int b) {this->m_pC->SetData(a,b);}
int GetData_f(){return this->m_pC->GetData();}
void Calc_f(){this->m_pC->Calc();}

private:
Unmanaged::UnmanagedClass * m_pC;
};
};

---<myLib.h ここまで>----



---<myLib.cpp>----

#include <windows.h>
#include "myLib.h"

namespace Unmanaged
{
TestUnmanagedClass::TestUnmanagedClass()
{
a = b = c = 0;
}


TestUnmanagedClass::~TestUnmanagedClass()
{
}


void TestUnmanagedClass::SetData(int p1,int p2)
{
a=p1;
b = p2;
}

int TestUnmanagedClass::GetData()
{
return c;
}

void TestUnmanagedClass::Calc()
{
c = a+b;
}
};


---<myLib.cpp ここまで>----

KAGAMI
会議室デビュー日: 2007/12/17
投稿数: 5
投稿日時: 2007-12-17 15:39

間違って、書き込んでしまいました。

改めて。

以下のようなコードに修正してみました。

---<myLib.h>----

#pragma once

#using <mscorlib.dll>

namespace Unmanaged;
{
class UnmanagedClass {
private:

int a,b,c; //プライベート変数

public:
UnmanagedClass(); //コンストラクタ
~UnmanagedClass(); //ディストラクタ
void SetData(int,int); //プライベート変数に値を設定
int GetData(); //プライベート変数Cの値を取得
void Calc(); //単に内部で c=a+bを計算する
};
};

namespace testSpace
{
public __gc class MClass
{
public:
MClass()
{
m_pC = new Unmanaged::UnmanagedClass();
}
~MClass() { delete this->m_pC; }
void SetData_f(int a,int b) {this->m_pC->SetData(a,b);}
int GetData_f(){return this->m_pC->GetData();}
void Calc_f(){this->m_pC->Calc();}

private:
Unmanaged::UnmanagedClass * m_pC;
};
};

---<myLib.h ここまで>----



---<myLib.cpp>----

#include <windows.h>
#include "myLib.h"

namespace Unmanaged
{
UnmanagedClass::UnmanagedClass()
{
a = b = c = 0;
}


UnmanagedClass::~UnmanagedClass()
{
}


void UnmanagedClass::SetData(int p1,int p2)
{
a=p1;
b = p2;
}

int UnmanagedClass::GetData()
{
return c;
}

void UnmanagedClass::Calc()
{
c = a+b;
}
};


---<myLib.cpp ここまで>----


[/quote]
1

スキルアップ/キャリアアップ(JOB@IT)