あなたの映画力を試せる!POPLETA映画検定(無料) >>

いつもお世話になっております。

http://satoshi.web5.jp/memo/connect_dll.htm

VC++2008のMFCプロジェクトにて、C#のdllの関数を扱いたく、
上記サイトを参考に実装してみました。

上記サイトでも挙げているように、C#dll内の関数の引数が、
整数・文字列の場合は、うまく動作するのですが、
引数に構造体を渡し、dllにて構造体のデータを設定してやる関数にて、
引数の構造体ポインタを、どのように渡してやれば良いのかが
分かりません。

具体的には、
VARIANTARGの配列をnewし(変数pVarg)、
pVargに型と変数をセットして、Invoke関数に渡しますが、
その際の、pVargにセットしてやる型が分かりません。

このような場合は、どうすれば良いのでしょう?
よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

 こんばんは。

補足頂きました。

[StructLayout(LayoutKind.Sequential)]
public struct ADUser
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string account;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string mail;
}

 ではないでしょうか。念の為にもう一度掲載します。

//C#サイド
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

namespace ClassLibrary1
{
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
[StructLayout(LayoutKind.Sequential)]
public struct ADUser
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string account;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string mail;
}

[MethodImpl(MethodImplOptions.Synchronized)]
public int fun(int intPtr)
{
System.IntPtr ptr = new System.IntPtr(intPtr);
ADUser test = (ADUser)Marshal.PtrToStructure(ptr, typeof(ADUser));
test.account = "123-456-7890";
test.name = "c++ to c# struct pointer";
test.mail = "xxx@abc.def.jp";
Marshal.StructureToPtr(test, ptr, true);
return 0;
}
}
}

//C++サイド
typedef struct ADUSER{
char account[100];
char name[100];
char mail[100];
}ADUser;

int main()
{
::CoInitialize( NULL );

CLSID clsid;
BSTR bstrDLL = _com_util::ConvertStringToBSTR( "ClassLibrary1.Class1" );
HRESULT hResult = ::CLSIDFromProgID(bstrDLL, &clsid);
if(!SUCCEEDED(hResult))
return 0;

IUnknown* pUnk = NULL;
hResult = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnk);
if(!SUCCEEDED(hResult))
return 0;

IDispatch* pDisp = NULL;
hResult = pUnk->QueryInterface( IID_IDispatch, (void**)&pDisp );
if(!SUCCEEDED(hResult))
return 0;

DISPID dispid = 0;
LPOLESTR fun = L"fun";
hResult = pDisp->GetIDsOfNames(IID_NULL, &fun, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if(!SUCCEEDED(hResult))
return 0;

ADUser test = {0};
DISPPARAMS params = {0};

params.cArgs = 1;
params.cNamedArgs = 0;
params.rgdispidNamedArgs = NULL;

VARIANTARG* pVarg = new VARIANTARG[params.cArgs];
::ZeroMemory(pVarg, sizeof(VARIANTARG) * params.cArgs);

pVarg[0].vt = VT_INT;
pVarg[0].intVal = (int)&test;

params.rgvarg = pVarg;

hResult = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);

::printf("[account : %s][name : %s][mail : %s]\n", test.account, test.name, test.mail);

::CoUninitialize();
::SysFreeString(bstrDLL);
delete []pVarg;

return 0;
}
    • good
    • 1
この回答へのお礼

うまくデータ取得出来るようになりました。

詳細なプログラムまで記載していただき、
とても分かりやすい説明ありがとうございました。

お礼日時:2009/12/07 16:23

 こんにちは。



 例えば、C++サイドが、

typedef struct
{
int a;
int b;
} TEST;

 であった場合、

TEST test = {0};
pVarg[0].vt = VT_INT;
pVarg[0].intVal = (int)&test;

 で、C#サイドが、

public void fun(int intPtr)
 
 ではないでしょうか(本当はC#サイドでSystem.IntPtrを引く方が良いと思うのですが、何故か上手くいきません)。
 ポインタをintで引く場合は以下で出来ています(VisualStudio2008にて確認)。
 参考程度で。

//C#サイド
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

namespace ClassLibrary1
{
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
[StructLayout(LayoutKind.Explicit)]
public struct Test
{
[FieldOffset(0)] public int a;
[FieldOffset(4)] public int b;
}

[MethodImpl(MethodImplOptions.Synchronized)]
public void fun(int intPtr)
{
System.IntPtr ptr = new System.IntPtr(intPtr);
Test test = (Test)Marshal.PtrToStructure(ptr, typeof(Test));
test.a = 15;
test.b = 800;
Marshal.StructureToPtr(test, ptr, true);
}
}
}

//C++サイド
#pragma pack(push, 4)
typedef struct
{
int a;
int b;
}TEST;
#pragma pack(pop)

int main()
{
::CoInitialize( NULL );

CLSID clsid;
BSTR bstrDLL = _com_util::ConvertStringToBSTR( "ClassLibrary1.Class1" );
HRESULT hResult = ::CLSIDFromProgID(bstrDLL, &clsid);
if(!SUCCEEDED(hResult))
return 0;

IUnknown* pUnk = NULL;
hResult = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnk);
if(!SUCCEEDED(hResult))
return 0;

IDispatch* pDisp = NULL;
hResult = pUnk->QueryInterface( IID_IDispatch, (void**)&pDisp );
if(!SUCCEEDED(hResult))
return 0;

DISPID dispid = 0;
LPOLESTR fun = L"fun";
hResult = pDisp->GetIDsOfNames(IID_NULL, &fun, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if(!SUCCEEDED(hResult))
return 0;

//このポインタを渡す
TEST test = {0};

DISPPARAMS params = {0};

//バリアントの数
params.cArgs = 1;
params.cNamedArgs = 0;
params.rgdispidNamedArgs = NULL;

//バリアントの割り当て
VARIANTARG* pVarg = new VARIANTARG[params.cArgs];
::ZeroMemory(pVarg, sizeof(VARIANTARG) * params.cArgs);

//バリアントにポインタを設定
pVarg[0].vt = VT_INT;
pVarg[0].intVal = (int)&test;

//パラメータにバリアントを設定
params.rgvarg = pVarg;

//PInvoke
hResult = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);

::printf("[a : %d][b : %d]\n", test.a, test.b);

//後始末
::CoUninitialize();
::SysFreeString(bstrDLL);
delete []pVarg;

return 0;
}

この回答への補足

回答ありがとうございます。

なんか、行けそうな感じなのですが、
うまく行きません。。。。

構造体のメンバ変数は、public string(C#側)のみで、
C++側の構造体のメンバを、charやBSTRにしてみたのですが、
PtrToStructureでポインタを構造体へ変換する箇所で
落ちてるみたいです。

C#のソースは今回初めて触るので、
分からない箇所ばかりなのですが、
下記に記載したC#側の構造体または、
C++の構造体に問題があるか
分かりますでしょうか?

C#構造体
 [StructLayout(LayoutKind.Sequential)]
public struct ADUser
{
[MarshalAs(UnmanagedType.LPStr)]
public string account; // アカウント(sAMAccount)
[MarshalAs(UnmanagedType.LPStr)]
public string name; // 名前(displayName)
[MarshalAs(UnmanagedType.LPStr)]
public string mail; // メール(mail)
  }

C++構造体(テストのためchar[100]で宣言してみました)
typedef struct ADUSER{
char account[100]; // アカウント(sAMAccount)
char name[100]; // 名前(displayName)
char mail[100]; // メール(mail)
}ADUser;


よろしくお願いします

補足日時:2009/12/04 11:51
    • good
    • 0

&pVarg じゃないですか?



下記URL等も参考にしてください。
※ポインタ渡し

参考URL:http://www.sasaraan.net/program/cpp/cpp_ptr.html

この回答への補足

&pVargじゃないかとの意味が分からないのですが、
VARIANTARGは構造体で、vtに型の種類を設定し、
pbstrValやplValといった共用体に、データ自体を設定するのですが、
独自構造体を設定する場合、
どの共用体に渡せばいいのかが分からないのです。
(というか、渡すことが可能なのかも分からない)

補足日時:2009/12/03 14:40
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC#で、C言語で作ったdllに文字列の参照渡し

Cで
int test(char* moji) {
  moji = "test";
  return 0;
}
のようなdllを作り、C#側から
  test(ref cs_moji);
としても変数cs_mojiに"test"という文字列は帰ってきませんでした。
数時間調べたりしてcs_mojiの型をstringやStringBuilder等としたのですが、どれもうまくいきませんでした。
ポインタのポインタを利用したときは文字列は帰ってきたものの文字化けがたくさんしていて理想とはかけ離れていました。
どのようにしたらCのdllからC#に文字列を送ることができるでしょうか。
初歩的な質問かもしれないですがよろしくお願いいたします。

Aベストアンサー

マネージドコードとアンマネージドコード間でのデータのやりとりになるので初歩的ではないです。

ひとまずこの辺は読んでおくべきかと思います。
http://msdn.microsoft.com/ja-jp/library/26thfadc%28v=vs.80%29.aspx
http://msdn.microsoft.com/ja-jp/library/e8w969hb%28v=vs.80%29.aspx

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

QC#で構造体の配列を持った構造体を使いたいのですが

C#で構造体の配列を持った構造体を使いたいのですが
Cならば
struct xyz {
struct abc _abc[32];
int index;
};
struct abc {
int a;
int b;
int c;
};

struct xyz _xyz[8];
xyz[0]._abc[3].b = 1;

のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません
うまくやる方法をどなたかご存知ないでしょうか

Visual Studio 2005行った場合
コンパイルで
構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するには、次元指定子を変数の識別子の前に指定します。固定サイズ バッファ フィールドを宣言するには、フィールド型の前に fixed キーワードを使用します
となり

fixed をつけると

固定サイズ バッファの型は次のうちの 1 つでなければなりません: bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float または double

となってしまいます

C#で構造体の配列を持った構造体を使いたいのですが
Cならば
struct xyz {
struct abc _abc[32];
int index;
};
struct abc {
int a;
int b;
int c;
};

struct xyz _xyz[8];
xyz[0]._abc[3].b = 1;

のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません
うまくやる方法をどなたかご存知ないでしょうか

Visual Studio 2005行った場合
コンパイルで
構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するに...続きを読む

Aベストアンサー

C# では、配列は「単なる連続したメモリ領域」ではなくて「添字によってオブジェクトを格納できるオブジェクト」であることに注意しなくてはいけません。つまり、C では配列は一種の構造体でしたが、C# では配列は参照型のオブジェクトです。
よって、C のように予めサイズを固定しておくということは基本的にできません。配列の大きさは配列のインスタンスが作られるときに動的に決まります。

C# では、参照型のオブジェクトを構造体のメンバにすることはあまりありません。null 値の扱いが面倒だからです。
また、C# では構造体の大きさは大きくとも 20 バイト程度までにします。C# では基本的に「構造体へのポインタ」はありません。巨大な構造体をそのまま扱うのはメモリの使い方の観点からいって非効率的です。

今回の件では、構造体ではなくクラスにするのがよいかと思われます。

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

QC# DLL エントリ ポイントが見つかりません。

C#で作成したDLLをC#から呼出したいのですが、うまくいきません。

// トリガ
private void button2_Click(object sender, EventArgs e)
{
string ans = DLL.moji();
MessageBox.Show(ans);
}

// DLL呼出し用クラス
class DLL
{
[DllImport("LibCsharp.dll")]
public static extern string moji();
}

// DLL(LibCsharp.dll内容)
class AddClass
{
public static string moji()
{
return ("テスト");
}
}

上記で実行すると「EntryPointNotFoundException DLL 'LibCsharp.dll' の 'moji' というエントリ ポイントが見つかりません。」となります。

プロジェクトの参照設定にはLibCsharpを追加しています。
Web上で調べたのですが、解決には至っておりません。

申し訳ありませんが、よろしくお願いします。

C#で作成したDLLをC#から呼出したいのですが、うまくいきません。

// トリガ
private void button2_Click(object sender, EventArgs e)
{
string ans = DLL.moji();
MessageBox.Show(ans);
}

// DLL呼出し用クラス
class DLL
{
[DllImport("LibCsharp.dll")]
public static extern string moji();
}

// DLL(LibCsharp.dll内容)
class AddClass
{
public static string moji()
{
...続きを読む

Aベストアンサー

#1です。

私もc#で簡易な独自ライブラリを構築しようとしていたので調べてみました。
結果として参照の追加でdllを直接、指定するだけで使用可能だと分かりました。
(「参照設定」右クリック→「参照の追加」→「参照」タブ選択→DLLを選択)


まず基本的な知識としてdllには3種類あると覚えて下さい。

・レガシー(古い遺産)dll
・active-x dll
・.net dll


私はレガシーdll時代の知識しかありませんでした。
この頃のdllを使用するためには、dll本体以外に以下のファイルが必要でした。

・ヘッダファイル
・ライブラリ(lib)ファイル
・defファイル(場合による)


c#で作られたdllは[.net dll]となり、[.net freamwork]上で動作する各種の言語で使用出来るようにするため、煩わしいlibファイルやヘッダファイル等を削除する方向でdllが進化しているのだと思われます。

ネット検索をしていて見つけたのですが、[.net dll]で作成されたFTPクライアントのライブラリがありました。
(.NET用FTPクラスライブラリ (TKFP.DLL) )

どの言語で作られているのか分かりませんが、[.net dll]で作られているため、c#およびvbで使用可能のようです。
追加したdll内に含まれているクラスや関数に対してオブジェクトブラウザで概要が表示出来るようにXMLファイルで概要を記述出来るようなのですが、詳細まで調べることが出来ませんでした。
(申し訳ありません。)

#1です。

私もc#で簡易な独自ライブラリを構築しようとしていたので調べてみました。
結果として参照の追加でdllを直接、指定するだけで使用可能だと分かりました。
(「参照設定」右クリック→「参照の追加」→「参照」タブ選択→DLLを選択)


まず基本的な知識としてdllには3種類あると覚えて下さい。

・レガシー(古い遺産)dll
・active-x dll
・.net dll


私はレガシーdll時代の知識しかありませんでした。
この頃のdllを使用するためには、dll本体以外に以下のファイルが必要でした。

・...続きを読む

QC#でint型をIntPtr型に変換したいです。

C#でint型をIntPtr型に変換したいです。

こちらのサイト↓
http://msdn.microsoft.com/ja-jp/library/a0f1byxz.aspx
は見たのですが、いまいち理解できず困っております。。
sampleがあれば良かったのですが。。

どなたかご教授お願いいたします。
よろしくお願いいたします。

Aベストアンサー

int 元データ;
IntPtr 新データ = new IntPtr(元データ);

QC# インスタンスの破棄

C#でインスタンスの破棄を明示的に行いたいのですが、
実際の開発現場では、どのように行っているのでしょうか?

自分で調べると「ガベージコレクタ」が暗黙的に行っているようですが明示的には行わないのが普通なのでしょうか?
もしくは、「Dispose」を使用して明示的に行うのが普通なのでしょうか?

実際に開発されている方からすると簡単な事かもしれませんが教えて頂けると助かります。

以上ですが、よろしくお願いいたします。

Aベストアンサー

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム系のオブジェクトや
データベースとのコネクションなどです。これは開発会社や
開発チーム、案件によって若干違っていて、徹底するところや
適当なところもあります。個人的には徹底したい派ですが。。。

ガベージコレクションが発生するとプログラムの実行動作が
遅くなり、また瞬間的に大きな負担がかかることがあります。
そのため全てをガベージコレクタに任せるのではなく、
明示的に開放できるもの、メモリを大量に消費するものは
その都度、適切に開放していくことで処理効率が良くなります。

プログラミング関連の調べ物で、サンプルソース等を見ることが
あるかと思います。この時サンプルで明示的に開放していたら、
それは明示的に開放したほうが良いもの、と思いましょう。
これだけでもステップアップになりますね。

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム...続きを読む

QC++DLLからC#へのコールバックに文字列の配列を渡したい

教えてください!
C++のアンマネージドDLLから、複数のファイル名(文字列)をC#に渡したいです。

ステップとしては、
C#から、C++のDLLの関数を最初に呼んで、コールバック関数を渡しています。
次に、DLLからコールバック関数を呼ぶ時に、複数のファイル名を渡したいです。

以下のコードを動かすと、、
C++からは2つ渡しているつもりなのに、
C#ではfilesがサイズ1のString配列として引数に入ってきます。

なぜでしょう?
またどうすればC#から複数受け取れるでしょうか?
教えてください!

C#
public delegate int StringArrayCallback(String[] files);

// C# -> C++
public static int start() {

StringArrayCallback cb = new StringArrayCallback(onReceivedFiles);
int ret = start(cb);
return ret;
}

// C++ -> C# callback
public static int onReceivedFiles(String[] files)
{
return 1;
}

C++コード
typedef int (__stdcall *OnReceivedFilesProc )(char**);
int start( OnReceivedFilesProc callback ) {
std::string message1_ = "from C++1";
std::string message2_ = "from C++2";
char* messages_[2] = { (char*)message1_.c_str(), (char*)message2_.c_str() };
int ret_ = callback(messages_);
std::cout << "[from c#]" << ret_;
}

教えてください!
C++のアンマネージドDLLから、複数のファイル名(文字列)をC#に渡したいです。

ステップとしては、
C#から、C++のDLLの関数を最初に呼んで、コールバック関数を渡しています。
次に、DLLからコールバック関数を呼ぶ時に、複数のファイル名を渡したいです。

以下のコードを動かすと、、
C++からは2つ渡しているつもりなのに、
C#ではfilesがサイズ1のString配列として引数に入ってきます。

なぜでしょう?
またどうすればC#から複数受け取れるでしょうか?
教えてください!
...続きを読む

Aベストアンサー

もうひとつの手段としてはやはりデリゲートの定義などを変更せざるを得ないのですがマーシャリング手段を指示しましょう

public delegate int StringArrayCallback2([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)] string[] files, int n);
とします nには配列の個数が返されます
と定義します

ArraySubType = UnmanagedType.LPStrはDLL側の文字セットにあわせましょう
Unicodeならば ArraySubType = UnmanagedType.LPWStr とします

コールバック関数の定義を
public static int onReceivedFiles2(string[] files, int n)
{
  return 1;
}
といった具合にしてやれば 引数files配列は要素n個として認識されます

下記参考URLなども熟読してましょう

参考URL:http://msdn.microsoft.com/ja-jp/library/z6cfh6e6(VS.80).aspx

もうひとつの手段としてはやはりデリゲートの定義などを変更せざるを得ないのですがマーシャリング手段を指示しましょう

public delegate int StringArrayCallback2([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)] string[] files, int n);
とします nには配列の個数が返されます
と定義します

ArraySubType = UnmanagedType.LPStrはDLL側の文字セットにあわせましょう
Unicodeならば ArraySubType = UnmanagedType.LPWStr とします

コールバック関数...続きを読む

Q同じソリューション内の別のプロジェクトのメソッド呼び出し

同じソリューション内の別のプロジェクトのメソッド呼び出し

お世話になっております。
Visual Studio でC#で開発をしております。
初心者です。

同じソリューション内にある別のプロジェクトのメソッドを呼び出す方法は
どの様にしたら宜しいのでしょうか。
下記の様に記述しましたら、
「静的でないフィールド、メソッド、またはプロパティ ~省略~ で、
 オブジェクト参照が必要です」と言うエラーが出てしまいます。
何か根本的に間違っているのかも知れません。

何卒、ご教授頂きたく宜しくお願い致します。

        記

呼び出し側
private void button1_Click(object sender, EventArgs e)

  呼び出し先のプロジェクト名.クラス名.メソッド名();
 }


呼び出される側
namespace プロジェクト名

public class クラス名

   メソッド名()
   {
     処理内容
    }
  }
 }

Aベストアンサー

ソリューション エクスプローラにおいて、呼び出し側のプロジェクト ツリーの「参照設定」を右クリックして、「参照の追加」を実行、ダイアログの「プロジェクト」タブにおいて、呼び出される側のプロジェクトを選択してOKを押してください。
Visual C#のインテリセンスが正常に機能し始めれば設定が成功しています。

なお、参照設定の追加により、参照されるアセンブリは参照するプロジェクトの出力フォルダに自動的にコピーされるようになります。
また、被参照アセンブリのプログラム デバッグ データベース ファイル(.pdb)も自動的にコピーされるので、被参照側のソースにブレークポイントを置いて参照側でデバッグを開始すると、きちんとブレークポイントで停止してくれます。

QC++/CLIで、アンマネージC++のDLLを使用する方法

こんにちは。
C++/CLIのプログラムで、アンマネージC++のDLLを使用したいと考えています。
ネット上をいろいろ調べたのですが、具体的な手段がわかりません。
見よう見まねで以下のようにサンプルを作成したのですが、コンパイルすら通る状況になりません。
かなり基本的な問題がありそうで申し訳ないのですが、下記の問題点を教えていただけないでしょうか。

また、参考になりそうなサイトなどありましたら教えていただけると大変助かります。

■アンマネージC++のDLL
VC++6.0で、以下のように、単にデバッグ文字列を書き出すだけのDLL関数を作成しました。
(このDLLが使用できることは他のVC++6.0プロジェクトで確認済みです)
/*-----Func.h-----*/
#ifndef __FUNC_H__
#define __FUNC_H__

AFX_EXT_CLASS void WINAPI ShowMessage();

#endif//__FUNC_H__

/*-----Func.cpp-----*/
#include "StdAfx.h"
#include "Func.h"
#include <stdio.h>

void WINAPI ShowMessage()
{
CString str = "This is The Message from DLL Func!\n";
OutputDebugString(str);
}

■C++/CLI でのDLL使用
Visual Studio2008にて、C++のCLRプロジェクトを作成して、以下のようにDLLを使用する準備を行いました。
1.ソリューションエクスプローラのヘッダフォルダに、Func.hを追加
2.プロジェクトのフォルダに、上記で作成したFuncのDLLとLIBファイルを置く。
3.プロジェクトの「プロパティ > C/C++ > プリプロセッサ > プリプロセッサの定義」に、"_AFXDLL"を追加
4.mainクラスのソースに以下を記述
/*----------*/
using namespace System;
#include "Func.h"
#using "ManagedDllApp.dll"

int main()
{
ShowMessage();
return 0;
}
/*----------*/

この状態でコンパイルすると、
「エラー3error C2144: 構文エラー : 'void' は ';' によって先行されなければなりません。d:\xxx\Func.h4Console
」等、Func.h周りで複数のエラーが出ます。
また、Func.hをインポートしないでコンパイルすると、
「エラー3fatal error C1113: #using が 'd:\xxx\manageddllapp.dll' で失敗しました。」と、Dllでエラーが出ます。

よろしくお願いいたします。

こんにちは。
C++/CLIのプログラムで、アンマネージC++のDLLを使用したいと考えています。
ネット上をいろいろ調べたのですが、具体的な手段がわかりません。
見よう見まねで以下のようにサンプルを作成したのですが、コンパイルすら通る状況になりません。
かなり基本的な問題がありそうで申し訳ないのですが、下記の問題点を教えていただけないでしょうか。

また、参考になりそうなサイトなどありましたら教えていただけると大変助かります。

■アンマネージC++のDLL
VC++6.0で、以下のように、単にデ...続きを読む

Aベストアンサー

 こんばんは。御礼頂きました。
 Func.hの中にインクルードし忘れがある様です。準備が出来たら、必ず「ソリューションのリビルド」をして下さい。
 以下は DLL->VC6.0Pro CLR->VC2005Pro で確認しています。

/*-----Func.h-----*/
#ifndef __FUNC_H__
#define __FUNC_H__

#include"afxver_.h"//此れと
#include"afxv_dll.h"//此れと
#include<windows.h>//此れをインクルード

AFX_EXT_CLASS void WINAPI ShowMessage();

#endif //__FUNC_H__

//以下はCLRアプリ側

/*-----stdafx.h-----*/
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または
// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
//
#pragma once

// TODO: プログラムに必要な追加ヘッダーをここで参照してください。
#include"func.h"
#pragma comment(lib, "libの名前.lib")

/*-----clrconsole.cpp-----*/
// clrconsole.cpp : メイン プロジェクト ファイルです。

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)
{
::ShowMessage();
return 0;
}

 こんばんは。御礼頂きました。
 Func.hの中にインクルードし忘れがある様です。準備が出来たら、必ず「ソリューションのリビルド」をして下さい。
 以下は DLL->VC6.0Pro CLR->VC2005Pro で確認しています。

/*-----Func.h-----*/
#ifndef __FUNC_H__
#define __FUNC_H__

#include"afxver_.h"//此れと
#include"afxv_dll.h"//此れと
#include<windows.h>//此れをインクルード

AFX_EXT_CLASS void WINAPI ShowMessage();

#endif //__FUNC_H__

//以下はCLRアプリ側

/*-----stdafx.h-...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング