Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.1 ) |
- 名前:管理人 日時:2016/08/14 03:51
私もあんまり詳しくありませんが、手順を確認しながらご説明します
<DLLの作成>
・プロジェクトの作成では「テンプレート -> Visual C++ -> Win32 -> Win32 プロジェクト」を選択します
プロジェクト名は例えば「DLLTest」とします
・アプリケーションの設定では
「アプリケーションの種類」を「DLL」に変更して、
「空のプロジェクト」にチェックを入れて「完了」を押します
・「DLLTest.cpp」を作成してプロジェクトに追加します、あと、「DLLTest.def」と「DLLTest_x64.def」という
ファイルを作成しておきます
( 私はいつもエクスプローラでプロジェクトのフォルダを開いて右クリック -> 新規作成 -> テキスト ドキュメント
を選択して「新しいテキスト ドキュメント.txt」を作成してからファイル名を変更する方法を採っています、
この場合拡張子を cpp や def に書き換える必要があるので、フォルダオプションで拡張子を表示するように
しておいてください )
・「DXライブラリの使い方」ページの「4.DXライブラリを使用するためのプロジェクトの設定を行う」と
同じ設定をします( なので、VisualC++ 版のDXライブラリもダウンロードしてください )
https://dxlib.xsrv.jp/use/dxuse_vc2013.html#R4
・それに加えて、プロジェクトのプロパティの「構成プロパティ」→「リンカー」→「入力」を選択します
「構成」を「すべての構成」に、プラットフォームを「Win32」にした状態で、
このページにある「モジュール定義ファイル」の部分に「DLLTest.def」と書き込んで「適用」を押します
・次に「ビルド」→「構成マネージャー」から64bit用の構成も追加します
「アクティブソリューションプラットフォーム」から「新規作成」を選びます
「新しいプラットフォームを入力または選択してください」から「x64」を選んで、
「設定のコピー元」を「Win32」になっていることを確認してから「OK」を押します
・次にプロジェクトのプロパティを開いて、「構成」を「すべての構成」に、プラットフォームを「x64」にします
・32bit用とファイル名を変えるために、プロジェクトのプロパティの「構成プロパティ」→「全般」の
ターゲット名を「$(ProjectName)」に少し書き足して「$(ProjectName)_x64」に変更します
・x64環境でも同じくプロジェクトのプロパティの「構成プロパティ」→「リンカー」→「入力」を選択して
「モジュール定義ファイル」の部分に「DLLTest_x64.def」と書き込んで「適用」を押します
・DLLTest.cpp の内容は例えば以下のような感じにします( 例として QTConj を DLL に使用できるようにします )
#include "DxLib.h"
extern "C"
{
extern DOUBLE4 __stdcall QTConj( DOUBLE4 A ) ;
}
// 共役クォータニオンを返す
DOUBLE4 __stdcall QTConj( DOUBLE4 A)
{
DOUBLE4 Result ;
Result.w = A.w ;
Result.x = -A.x ;
Result.y = -A.y ;
Result.z = -A.z ;
return Result ;
}
関数の定義は extern "C" { } で囲み、関数の呼び出し形式は __stdcall にしておきます
・DLLTest.def の内容は以下のようにします
LIBRARY DLLTest
EXPORTS
QTConj
LIBRARY の横にDLLのファイル名( の、拡張子部分( .dll )を抜いたもの )を記述、
DLLとして外部から呼び出せるようにする関数を EXPORTS 以下に記述します
・同じく DLLTest_x64.def の内容は以下のようにします
LIBRARY DLLTest_x64
EXPORTS
QTConj
・次に「ビルド」→「バッチビルド」でバッチビルドダイアログを表示して、
「Release | Win32」と「Release | x64」の「ビルド」にチェックを入れてビルドします、
これで DLLTest.dll と DLLTest_x64.dll が作成されます
これで DXライブラリ.NET版で言うところの DxLib.dll と DxLib_x64.dll に相当するものが
それぞれ「DLLTest\Release\DLLTest.dll」と「DLLTest\x64\Release\DLLTest_x64.dll」に
作成されるのですが、ゆーすけさんは DxLib.dll 、DxLib_x64.dll をVBで使用するに当たって
どのような方法を使用しているのでしょうか?
( 以下のような DLL 内の関数を使用するための定義を自力で書かれているのでしょうか?
[DllImport("DLLTest.dll", EntryPoint="QTConj")]
extern static DX.DOUBLE4 QTConj_x86( DX.DOUBLE4 A );
[DllImport("DLLTest_x64.dll", EntryPoint="QTConj")]
extern static DX.DOUBLE4 QTConj_x64( DX.DOUBLE4 A );
public static DX.DOUBLE4 QTConj( DX.DOUBLE4 A )
{
if( System.IntPtr.Size == 4 )
{
return QTConj_x86( A );
}
else
{
return QTConj_x64( A );
}
}
それとも DxLibDotNet.dll を使用しているのでしょうか? )
> ・VBではNET版ライブラリを使うため入力パラメータはDX.VECTOR_D型になるが、それとアンマネージドDLL中のVECTOR_D型の相互変換を
> どうすべきか
VECTOR_D 型を引数としたり戻り値としたりする関数として定義すれば普通に使うことができます
 |
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.2 ) |
- 名前:ゆーすけ 日時:2016/08/14 06:07
サンプルコードありがとうございます。
DLLの作法については別途ネット上等で調べて試行錯誤するしかないかと思っていましたので助かりました。
一眠りしてから教えていただいた内容に従ってサンプルDLLを作ってみたいと思います。
>ゆーすけさんは DxLib.dll 、DxLib_x64.dll をVBで使用するに当たってどのような方法を使用しているのでしょうか?
DxLibDotNet.dllを使用しています。
なお、恥ずかしながらVB.NETでアンマネージドDLLを呼び出す方法はまだはっきりと理解できていませんので、サンプルDLLを作ったら
呼び出し方についてはいろいろ試行錯誤してみようと思っているところです・・・。
ところで今回考えているDLLは基本32ビット版なのですが、その場合でも64bit版の設定やモジュール定義ファイル等は必要なのでしょうか?
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.3 ) |
- 名前:ゆーすけ 日時:2016/08/15 01:05
先ほどサンプルコードを参考にしてクォータニオンを用いたベクトルの回転を行う関数をDLL化したものを作り、動作確認を兼ねて別のサンプルプログラム
(作成はVC++です)で試してみました(Qternion型の構造体、複数の関数の使用テストを兼ねてサンプルコードに付け足しをしています)。
計算部分のコードは前回のスレッドにあった管理者様のコードを一部改変(math.hをインクルードしてsqrt,sin,cosの関数を用いたものに書き換え)したものを
使わせていただきましたが、どうも呼び出し側のプログラムで上手く動作してくれません。
---以下DLLのソースファイル---
#include "DxLib.h"
#include "math.h"
typedef struct
{
double T;
double X;
double Y;
double Z;
}Qternion;
extern "C"
{
extern VECTOR_D _stdcall VRotQ(VECTOR_D Pnt, VECTOR_D Axis, double Angle);
extern Qternion _stdcall QTConj(Qternion A);
}
VECTOR_D _stdcall VRotQ(VECTOR_D Pnt, VECTOR_D Axis, double Angle)
{
VECTOR_D Result;
DOUBLE4 Temp;
DOUBLE4 RotQ;
double Sin;
double Square;
double Size;
Square = Axis.x * Axis.x + Axis.y * Axis.y + Axis.z * Axis.z;
if (Square < 0.0000001)
{
return VGetD(-1.0, -1.0, -1.0);
}
Size = sqrt(Square);
Angle = -0.5*Angle;
Sin = sin(Angle);
RotQ.w = cos(Angle);
RotQ.x = Axis.x / Size * Sin;
RotQ.y = Axis.y / Size * Sin;
RotQ.z = Axis.z / Size * Sin;
Temp.w = Pnt.x * RotQ.x + RotQ.y * Pnt.y + RotQ.z * Pnt.z;
Temp.x = Pnt.x * RotQ.w - RotQ.y * Pnt.z + RotQ.z * Pnt.y;
Temp.y = Pnt.y * RotQ.w - RotQ.z * Pnt.x + RotQ.x * Pnt.z;
Temp.z = Pnt.z * RotQ.w - RotQ.x * Pnt.y + RotQ.y * Pnt.x;
Result.x = RotQ.x * Temp.w + Temp.x * RotQ.w + (Temp.y * RotQ.z - Temp.z * RotQ.y);
Result.y = RotQ.y * Temp.w + Temp.y * RotQ.w + (Temp.z * RotQ.x - Temp.x * RotQ.z);
Result.z = RotQ.z * Temp.w + Temp.z * RotQ.w + (Temp.x * RotQ.y - Temp.y * RotQ.x);
return Result;
}
Qternion _stdcall QTConj(Qternion A)
{
Qternion Result;
Result.T = A.T;
Result.X = -A.X;
Result.Y = -A.Y;
Result.Z = -A.Z;
return Result;
}
---ソースここまで---
---以下モジュール定義ファイル---
LIBRARY DLLTest
EXPORTS
VRotQ
QTConj
---ここまで---
長くなるので次に呼び出し側のプログラムのソースを貼ります
 |
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.4 ) |
- 名前:ゆーすけ 日時:2016/08/15 01:07
以下呼び出し側のプログラムです。
---以下プログラムソース---
#include "DxLib.h"
#include "math.h"
#include "Windows.h"
#include "time.h"
//DLLで使う構造体を宣言
typedef struct
{
double T;
double X;
double Y;
double Z;
}Qternion;
//DLL中の関数を宣言
typedef VECTOR_D (*FUNC1)(VECTOR_D Pnt, VECTOR_D Axis, double Angle);
typedef Qternion (*FUNC2)(Qternion A);
// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
VECTOR_D PosIn, AxisIn,ResultM,ResultQ;
double AngleIn;
int LoopNum,ETimeM,ETimeQ;
clock_t start, end;
FUNC1 VROTQ;
FUNC2 QTCONJ;
Qternion CJVal;
CJVal.T = 1;
CJVal.X = 2;
CJVal.Y = 3;
CJVal.Z = 4;
HMODULE DLLhandle = LoadLibrary(_T(".\\DLLTest.dll"));
if (DLLhandle == NULL)
{
return 0;
}
VROTQ = (FUNC1)GetProcAddress(DLLhandle, "VRotQ");
QTCONJ = (FUNC2)GetProcAddress(DLLhandle, "QTConj");
if (VROTQ == NULL || QTCONJ == NULL)
{
FreeLibrary(DLLhandle);
}
else
{
PosIn = VGetD(1, 2, 3);
AxisIn = VGetD(4, 5, 6);
AngleIn = 7;
LoopNum = 3;
start = clock();
for (int i = 0; i < LoopNum; ++i)
{
ResultM = VTransformD(PosIn,MGetRotAxisD(AxisIn,AngleIn));
}
end = clock();
ETimeM = end - start;
start = clock();
for (int i = 0; i < LoopNum; ++i)
{
ResultQ = VROTQ(PosIn, AxisIn, AngleIn);
}
end = clock();
ETimeQ = end - start;
CJVal = QTCONJ(CJVal);
}
ChangeWindowMode(TRUE);
SetGraphMode(400, 300, 32);
if (DxLib_Init() == -1) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
DrawFormatString(10, 10, GetColor(0, 255, 0),"回転行列:%dms",ETimeM);
DrawFormatString(10, 30, GetColor(0, 255, 0), "%.3f, %.3f, %.3f", ResultM.x, ResultM.y, ResultM.z);
DrawFormatString(10, 70, GetColor(0, 0, 255),"クォータニオン:%dms",ETimeQ);
DrawFormatString(10, 90, GetColor(0, 0, 255), "%.3f, %.3f, %.3f", ResultQ.x, ResultQ.y, ResultQ.z);
WaitKey(); // キー入力待ち
DxLib_End(); // DXライブラリ使用の終了処理
return 0; // ソフトの終了
}
---ソースここまで---
これを1行ずつステップインしていくとstart = clock() やVRotQ中の平方根、三角関数等の箇所にさしかかったところで「ソースが見つかりません」
というエラーが出て先に進まなくなってしまいます。
DLL側でmath.hはインクルードしてありますし、DLLのビルド自体はできていて、それを呼び出し側プログラムのプロジェクトのDebugフォルダの
実行ファイルと同じ場所に置いてはいるのですが・・・。
何か見落とし、根本的な勘違い等がありましたら指摘していただければと思います。
 |
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.5 ) |
- 名前:管理人 日時:2016/08/15 03:17
> DxLibDotNet.dllを使用しています。
では、DxLibDotNet.dll に相当する dll の作成方法も…
・前回の説明で作成した「DLLTest」プロジェクトを開きます
・「ファイル」→「新規作成」→「プロジェクト」をクリックして、「新しいプロジェクト」のダイアログを開きます
・「インストール済み」→「テンプレート」→「Visual C#」→「クラスライブラリ」を選択して、名前を入力して
( 例えば「DLLTestDotNet」とします )、「ソリューション」を「ソリューションに追加」に設定してから「OK」を押します。
・新規作成時に「Class1.cs」というファイルが自動的に追加されますが、それをそのまま使用しても良いですし、
新たに「DLLTest.cs」などのソースファイルを追加しても良いです、今回は新たに「DLLTest.cs」を追加して、
Class1.cs は削除する形で進めます
・加えて、新しく作成された DLLTestDotNet プロジェクトにDXライブラリ.NET版に含まれている
DxLibDotNet.dll の参照を追加します( DX.DOUBLE4 などを使うため )、参照の追加の仕方は
通常の DxLibDotNet.dll の参照の追加の仕方と同じです( 「プロジェクト」→「参照の追加」を使用する方法 )
・DLLTest.cs に以下の内容を記述します
using System.Runtime.InteropServices;
using DxLibDLL;
namespace DLLTestDotNet
{
public static class DLLTest
{
[DllImport("DLLTest.dll", EntryPoint = "QTConj")]
extern static DX.DOUBLE4 QTConj_x86(DX.DOUBLE4 A);
[DllImport("DLLTest_x64.dll", EntryPoint = "QTConj")]
extern static DX.DOUBLE4 QTConj_x64(DX.DOUBLE4 A);
public static DX.DOUBLE4 QTConj(DX.DOUBLE4 A)
{
if (System.IntPtr.Size == 4)
{
return QTConj_x86(A);
}
else
{
return QTConj_x64(A);
}
}
}
}
・「ビルド」→「バッチビルド」をクリックしてバッチビルドダイアログを表示します
・DLLTestDotNet Release|Any CPU にチェックを入れて「ビルド」ボタンを押します
・ビルドが成功すれば DLLTest\DLLTestDotNet\bin\Release にDXライブラリ.NET版の DxLibDotNet.dll に相当する
DLLTestDotNet.dll というファイルが作成されます
後はこちらを DxLibDotNet.dll と同じような方法で VB で使用していただくだけです
> なお、恥ずかしながらVB.NETでアンマネージドDLLを呼び出す方法はまだはっきりと理解できていませんので、サンプルDLLを作ったら
> 呼び出し方についてはいろいろ試行錯誤してみようと思っているところです・・・。
DXライブラリの.NET版と同じ手順で使用できます、「プロジェクト」→「参照の追加」で DLLTestDotNet.dll を追加して使用します
> ところで今回考えているDLLは基本32ビット版なのですが、その場合でも64bit版の設定やモジュール定義ファイル等は必要なのでしょうか?
.NETのVBのプロジェクトを明示的に32bitアプリとしてのみ動作するように設定してあれば64bit版の設定やDLLの作成は
必要ありませんが、基本的に.NETアプリは64bit OSでは64bitアプリとして、32bit OSでは32bitアプリとして
動作するので、明示的に32bitアプリとしてのみ動作するように設定しないのであれば64bitアプリ用の設定やDLLの作成は必要です
( そして if (System.IntPtr.Size == 4) で 32bitアプリとして動作しているか 64bitアプリとして動作しているか
を判別して、使用するDLLを変更します )
> 先ほどサンプルコードを参考にしてクォータニオンを用いたベクトルの回転を行う関数をDLL化したものを作り、動作確認を兼ねて別のサンプルプログラム
> (作成はVC++です)で試してみました(Qternion型の構造体、複数の関数の使用テストを兼ねてサンプルコードに付け足しをしています)。
んん? 本番(?)では VB で使用されるのですよね?
とりあえず「__stdcall」( 最初の _ は2文字 )を「_stdcall」( 最初の _ を1文字 )で記述されてしまっている
ようですので、こちらは最初の _ を2文字の「__stdcall」に変更してください
あと、DLLを使用する側のプログラムのこちらにも
//DLL中の関数を宣言
typedef VECTOR_D (*FUNC1)(VECTOR_D Pnt, VECTOR_D Axis, double Angle);
typedef Qternion (*FUNC2)(Qternion A);
__stdcall の記述が必要ですので、次のようにすれば動作すると思います
//DLL中の関数を宣言
typedef VECTOR_D ( __stdcall *FUNC1)(VECTOR_D Pnt, VECTOR_D Axis, double Angle);
typedef Qternion ( __stdcall *FUNC2)(Qternion A);
 |
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.6 ) |
- 名前:SUIMA 日時:2016/08/15 03:47
途中から失礼致します。
ゆーすけ さんのソースコードをVisual Studio 2015にてC++としてビルドし実行してみました。
私の環境では、ゆーすけさんの仰るmath関数での「ソースが見つかりません」のエラーは発生しませんでした。
ですが、ソース上で気になる点がありましたので書かせていただくと
呼び出し側 16,17行目を
typedef VECTOR_D(_stdcall *FUNC1)(VECTOR_D Pnt, VECTOR_D Axis, double Angle);
typedef Qternion(_stdcall *FUNC2)(Qternion A);
のように変更したほうが良いかと思いました。
_stdcall*FUNC1 の様に記述しないと、私の環境では呼び出し規約が異なると例外を吐きました。
少しでも、問題解決のお役に立てれば幸いです。
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.7 ) |
- 名前:ゆーすけ 日時:2016/08/15 07:06
管理人様、SUIMA様、レスありがとうございます。
DotNet版のDLLの作り方まで教えていただいて助かりました。
ご指摘いただいたとおりstdcallの部分を訂正・追加したところ、ビルドしたプログラムもちゃんと結果を返すようになりました。
デバッグでのステップイン実行時には相変わらず〜.asmが見つからないとエラーを吐きますが、ビルドしたプログラムは問題ないようです。
DotNet版のDLLについては夜にでも試してみたいと思います。
>.NETのVBのプロジェクトを明示的に32bitアプリとしてのみ動作するように設定してあれば64bit版の設定やDLLの作成は必要ありませんが
なるほど・・・こちらでは明示的に32bitアプリ決めうちにしていますので64bit版はなくても大丈夫のようです。
>んん? 本番(?)では VB で使用されるのですよね?
はい、最終的にはVBで使用予定ですが、その前にまずDLLとしてマトモに使えるかどうかを試す目的でVC++でサンプルプログラムを書いていました。
DLLとしては動作することが確認できましたので、あとは教えていただいたようにDotNet版のDLLを作ってVBで試してみたいと思います。
結果はまた後ほど報告させていただきます。
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.8 ) |
- 名前:ゆーすけ 日時:2016/08/17 01:09
うーん・・・DotNet版のDLLを書いてみましたが上手くいってないようです。
以下関数名をちょっと変えたので再度コードを貼ります。
※DLLTest.dllのソース
#include "DxLib.h"
#include "math.h"
typedef struct
{
double T;
double X;
double Y;
double Z;
}Qternion;
extern "C"
{
extern VECTOR_D __stdcall QTRotation(VECTOR_D Pnt, VECTOR_D Axis, double Angle);
extern Qternion __stdcall QTConj(Qternion A);
}
VECTOR_D __stdcall QTRotation(VECTOR_D Pnt, VECTOR_D Axis, double Angle)
{
VECTOR_D Result;
DOUBLE4 Temp;
DOUBLE4 RotQ;
double Sin;
double Square;
double Size;
Square = Axis.x * Axis.x + Axis.y * Axis.y + Axis.z * Axis.z;
if (Square < 0.0000001)
{
return Pnt;
}
Size = sqrt(Square);
Angle = -0.5 * Angle;
Sin = sin(Angle) / Size;
RotQ.w = cos(Angle);
RotQ.x = Axis.x * Sin;
RotQ.y = Axis.y * Sin;
RotQ.z = Axis.z * Sin;
Temp.w = Pnt.x * RotQ.x + RotQ.y * Pnt.y + RotQ.z * Pnt.z;
Temp.x = Pnt.x * RotQ.w - RotQ.y * Pnt.z + RotQ.z * Pnt.y;
Temp.y = Pnt.y * RotQ.w - RotQ.z * Pnt.x + RotQ.x * Pnt.z;
Temp.z = Pnt.z * RotQ.w - RotQ.x * Pnt.y + RotQ.y * Pnt.x;
Result.x = RotQ.x * Temp.w + Temp.x * RotQ.w + (Temp.y * RotQ.z - Temp.z * RotQ.y);
Result.y = RotQ.y * Temp.w + Temp.y * RotQ.w + (Temp.z * RotQ.x - Temp.x * RotQ.z);
Result.z = RotQ.z * Temp.w + Temp.z * RotQ.w + (Temp.x * RotQ.y - Temp.y * RotQ.x);
return Result;
}
Qternion __stdcall QTConj(Qternion A)
{
Qternion Result;
Result.T = A.T;
Result.X = -A.X;
Result.Y = -A.Y;
Result.Z = -A.Z;
return Result;
}
※モジュール定義ファイル
LIBRARY DLLTest
EXPORTS
QTRotation
QTConj
※DLLTest.csの中身
using System.Runtime.InteropServices;
using DxLibDLL;
namespace DLLTestDotNet
{
public static class DLLTest
{
[DllImport("DLLTest.dll", EntryPoint = "QTRotation")]
extern static DX.VECTOR_D QTRotation_x86(DX.VECTOR_D Pnt, DX.VECTOR_D Axis, double Angle);
public static DX.VECTOR_D QTRotation(DX.VECTOR_D Pnt,DX.VECTOR_D Axis,double Angle)
{
if(System.IntPtr.Size==4)
{
return QTRotation_x86(Pnt, Axis, Angle);
}
else
{
return QTRotation_x86(Pnt, Axis, Angle);
}
}
}
}
ビルドは通ってDLLTest.dllとそのDotNet版は生成されるのですが、VB側でDotNetの参照を追加してもQTRotation関数が使えるようになりません。
一応VB側のプロジェクトはx86決め打ちにしてるはずなのですが・・・
ご教示のほどよろしくお願いします。
 |
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.9 ) |
- 名前:ゆーすけ 日時:2016/08/17 01:13
それと追加で質問なのですが、↑のDLLTest.cpp中でQternion構造体を宣言していますが、この型をVB側で使えるようにするためには
どのようにすればよいのでしょうか?
VB中でどうもQternion型の変数を上手く宣言できないようです。
実際のDLLでは独自の構造体を作ってそのデータをDLL側に渡す必要があるので、この点についてもご教示お願いします。
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.10 ) |
- 名前:管理人 日時:2016/08/18 00:38
> VB側でDotNetの参照を追加してもQTRotation関数が使えるようになりません。
使えない、とはどのような状況でしょうか?
using DLLTestDotNet; を記述した上で DLLTest.QTRotation を使用しようとしても
ビルドエラーになってしまうということでしょうか?
> ↑のDLLTest.cpp中でQternion構造体を宣言していますが、この型をVB側で使えるようにするためには
> どのようにすればよいのでしょうか?
namespace DLLTestDotNet
{
public static class DLLTest
{
<<<< QTRotation の定義もしているこの部分に >>>>
}
}
↓こちらの記述を追加すれば DLLTest.Qternion の記述で使えるようになります
( using DLLTestDotNet; を指定していない場合は DLLTestDotNet.DLLTest.Qternion )
[StructLayout(LayoutKind.Explicit)]
public struct Qternion
{
[FieldOffset(0)] public double T;
[FieldOffset(8)] public double X;
[FieldOffset(16)] public double Y;
[FieldOffset(24)] public double Z;
};
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.11 ) |
- 名前:ゆーすけ 日時:2016/08/19 00:14
回答ありがとうございます。
>using DLLTestDotNet; を記述した上で DLLTest.QTRotation を使用しようとしても
>ビルドエラーになってしまうということでしょうか?
ビルドは通るのですがVB側で使おうとしてもIntelliSenseの候補一覧にQTRotationが出てこなかったので頭を抱えてました・・・
恥ずかしながら頭にDLLTest.をつけるのを忘れていたようです。
ちなみにDotNet版DLL中での構造体の定義についてですが、Explicit&FieldOffSetで明示的に指定している理由は何故なのでしょうか?
(SequentialにしてC++版のDLLと同じ順番でメンバー変数を並べるのだとどこか不味いのかな、と思ったもので・・・)
もう一点、.NET版のDXライブラリのreadme.txtには「ポインタを返す関数は使えない」とありますが、これは.NET版のDLL全般に言える制約なのでしょうか?
実は今回作ろうとしているDLLで戻り値として複数の値を返すようにしたいと思っていて、その複数の値の中に構造体変数の配列も含まれているのですが、
そのようなDLLは実現できるのでしょうか?
例えばDLLで演算を行い、その結果をint A, double Bという数値と、Struct1という型(VECTOR_D型のメンバー変数P,Q,R,Sをもつ)で要素数が20ある配列として
返したいのですが、そういったDLLを実現できるのかということです。
返り値として配列を返したい場合、先頭のアドレスをポインタとして返してあとは呼び出し元で処理するのかと思っていたのですが、.NET版のDLLの制約を見ると
ひょっとして配列を返すDLLはプログラミング言語の仕様上の制約で実現できないのではないかとふと気になりました。
この点についてもご教示いただけると幸いです。
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.12 ) |
- 名前:管理人 日時:2016/08/19 00:59
> ちなみにDotNet版DLL中での構造体の定義についてですが、Explicit&FieldOffSetで明示的に指定している理由は何故なのでしょうか?
こちらの記事にありますように
<@IT Win32 APIやDLL関数に構造体を渡すには?>
http://www.atmarkit.co.jp/fdotnet/dotnettips/026w32struct/w32struct.html
『.NET Frameworkでは、通常、アクセスに最適な配置となるように、CLRがメモリ上における構造体の
各メンバの配置を決定する。つまり、単純に同じ構造体をC#などで宣言しただけでは、各メンバの
オフセットをDLL側と確実に一致させることは不可能である』
とのことなので、明示的に指定しています
> もう一点、.NET版のDXライブラリのreadme.txtには「ポインタを返す関数は使えない」とありますが、これは.NET版のDLL全般に言える制約なのでしょうか?
この readme.txt を作成した時点では知りませんでしたが、C# であればポインタを返す関数も使えるようです
C# 以外については詳しくないので分かりません( C# についても詳しくはありませんが… )
> 実は今回作ろうとしているDLLで戻り値として複数の値を返すようにしたいと思っていて、その複数の値の中に構造体変数の配列も含まれているのですが、
> そのようなDLLは実現できるのでしょうか?
C++用の DLL は作成することはできると思いますが、それを .NET用の DLL で実装したり、.NET用の DLL を使って
VB で使用できるかどうかはわかりません、ただ、『.NET( C# や VB.NET など ) での「配列」と C++ での「配列」は別物』なので、
仮に実現できたとしても煩雑なプログラムになる可能性があります
( こちらのご質問を拝見する限り
<Yahoo!知恵袋 C#で配列や構造体のアドレスをIntPtrに渡すにはどうしたら良いでしょう>
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1256753257
unsafe を使用すれば C# では( 煩雑ながら )実現できそうですが、VB でも同様の方法で実現できるのかは分かりません )
 |
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.13 ) |
- 名前:ゆーすけ 日時:2016/08/19 18:39
ありがとうございます。
><@IT Win32 APIやDLL関数に構造体を渡すには?>
↑同じサイトを見ていて別の箇所に
C言語などの構造体と同様に、メンバが宣言された順に配置されるようにするには、LayoutKind.Sequentialという値を指定すればよい。
これらの話を踏まえて、前出のPOINT構造体と等価なものをC#で定義すると次のようになる。
[StructLayout(LayoutKind.Sequential)]
struct POINT {
public int x;
public int y;
}
と解説されていたので、管理人様のコードの部分はExplicit&FieldOffSetではなくSequentialにして上記のコードのように書いても
同じように動くのでは?と思ったのですがそうではないということでしょうか?
>C++用の DLL は作成することはできると思いますが、それを .NET用の DLL で実装したり、.NET用の DLL を使って
>VB で使用できるかどうかはわかりません
なかなか難しそうですね・・・
とはいえ目的のプログラムの核になる部分のためどうにか実装したいと思っているので頑張ってみます。
VC++でもフォームアプリケーションは作れなくはなさそうなんですが、過去ログを見たところその状態だとDXライブラリとの併用が
かなり厳しくなるようでしたので・・・
|
Re: アンマネージドDLLにおけるDXライブラリの使用 ( No.14 ) |
- 名前:管理人 日時:2016/08/21 03:07
> と解説されていたので、管理人様のコードの部分はExplicit&FieldOffSetではなくSequentialにして上記のコードのように書いても
> 同じように動くのでは?と思ったのですがそうではないということでしょうか?
すみません、その通りです
ゆーすけさんの No.11 のお書き込みの内容をちゃんと理解できていませんでした m(_ _;m
かなり昔のことなので若干合っているか怪しいですが、きっちりオフセットを指定したくて
[StructLayout(LayoutKind.Explicit)] と FieldOffset にした記憶があります
C++ でも例えば
struct A
{
unsigned char B ;
int C ;
} ;
とした場合、特に指定が無い場合は
struct A
{
unsigned char B ; <- 0 byte
int C ; <- 4 byte
} ;
と、B のサイズは 1バイトにもかかわらず C は 4バイト目に配置されたりするので、
「C# ではその辺りがどのように解釈されるんだろう? 気持ち悪いからきっちり指定しよう」という感じで
[StructLayout(LayoutKind.Explicit)] と FieldOffset を使うことにしました( 多分 )
|