いつもお世話になっております。
http://satoshi.web5.jp/memo/connect_dll.htm
VC++2008のMFCプロジェクトにて、C#のdllの関数を扱いたく、
上記サイトを参考に実装してみました。
上記サイトでも挙げているように、C#dll内の関数の引数が、
整数・文字列の場合は、うまく動作するのですが、
引数に構造体を渡し、dllにて構造体のデータを設定してやる関数にて、
引数の構造体ポインタを、どのように渡してやれば良いのかが
分かりません。
具体的には、
VARIANTARGの配列をnewし(変数pVarg)、
pVargに型と変数をセットして、Invoke関数に渡しますが、
その際の、pVargにセットしてやる型が分かりません。
このような場合は、どうすれば良いのでしょう?
よろしくお願いします。
No.1
- 回答日時:
この回答への補足
&pVargじゃないかとの意味が分からないのですが、
VARIANTARGは構造体で、vtに型の種類を設定し、
pbstrValやplValといった共用体に、データ自体を設定するのですが、
独自構造体を設定する場合、
どの共用体に渡せばいいのかが分からないのです。
(というか、渡すことが可能なのかも分からない)
No.2
- 回答日時:
こんにちは。
例えば、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, ¶ms, 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;
よろしくお願いします
No.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, ¶ms, NULL, NULL, NULL);
::printf("[account : %s][name : %s][mail : %s]\n", test.account, test.name, test.mail);
::CoUninitialize();
::SysFreeString(bstrDLL);
delete []pVarg;
return 0;
}
うまくデータ取得出来るようになりました。
詳細なプログラムまで記載していただき、
とても分かりやすい説明ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# C言語で構造体の参照渡しができません 2 2022/12/18 21:22
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- Excel(エクセル) Indirect関数について、Formulatextで抽出した数式を参照したい。 1 2022/12/15 11:16
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- Windows 10 IT初心者です! powershellで以下のようなエラーが出ました オブジェクト参照がオブジェクト 1 2023/05/17 11:30
- Excel(エクセル) エクセル関数のスペシャリストの方、教えてください。 写真のように A列にはデータ C列にはデータの中 7 2022/04/09 00:15
このQ&Aを見た人はこんなQ&Aも見ています
-
性格の違いは生まれた順番で決まる?長男長女・中間子・末っ子・一人っ子の性格の傾向
同じ環境で生まれ育っても、生まれ順で性格は違うものなのだろうか。家庭教育研究家の田宮由美さんに教えてもらった。
-
C言語で、メモリを解放しないで終わるプログラム
C言語・C++・C#
-
char*を初期化したいのですが
C言語・C++・C#
-
CFileDialogの最初のディレクトリ設定
C言語・C++・C#
-
-
4
他の.CPPファイルに定義した関数を呼び出す方法について
C言語・C++・C#
-
5
適切な変換関数が存在しない???
C言語・C++・C#
-
6
unsigned char配列への入力の仕方
C言語・C++・C#
-
7
C#でstringをポインタとして渡す
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数のボタンを配置し、それぞ...
-
式の型は配列型で int に解決済...
-
java spring でエラーが出て困...
-
(Swing)JTextFieldを半角のみ入...
-
c# デリゲート関連の命名について
-
Javaでポインタ的なことはでき...
-
C#で実行時にメソッドの返り値...
-
sin曲線とcos曲線を描くプログ...
-
javaで次のような図の絵を描く...
-
行の途中から読み込む方法
-
初心者ですが、今javaで簡単な...
-
「配列定数は、イニシャライザ...
-
javaのエラーの意味がわかりま...
-
【C#】フォームをなめらかに移動
-
C++からC#のdllを参照する際、...
-
6桁の数字を重複なしでランダム...
-
intが負の時に投げる例外はあり...
-
Java 初心者 int型の取り扱い方
-
三目並べ(Tick-Tack-Toe)をJav...
-
C#2005 Imagelistの余白の除去...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
javaでcsvファイル読込時の改行...
-
java spring でエラーが出て困...
-
DataSet(DataTable)の使い方
-
「配列定数は、イニシャライザ...
-
JUnit4のアノテーションについて
-
C#で実行時にメソッドの返り値...
-
JAVA エラー 式の開始が不正で...
-
JAVAでCの関数ポインタのような...
-
c# デリゲート関連の命名について
-
java streamでenum配列への変換
-
intが負の時に投げる例外はあり...
-
Java 初心者 int型の取り扱い方
-
C++からC#のdllを参照する際、...
-
アンマネージDLLで、ダイアログ...
-
【C#】フォームをなめらかに移動
-
(Swing)JTextFieldを半角のみ入...
-
Javaで簡単なアニメーションを...
-
javaのエラーの意味がわかりま...
-
C#で判断文(三択)の省略形は...
-
共有メモリについて
おすすめ情報