- PR -

DLL内の関数の戻り値を構造体で受け取るには…。

投稿者投稿内容
優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-19 09:33
優希です。


表題の内容からは外れてしまうのですが、
DLLの読込み作業でエラーが出てしまいました。

以下のようにDLLを読み込もうとしたのですが…。

コード:
// ヘッダファイルをインクルード
#include "Sample.h"

// Sample.dllのlibをリンク
#pragma comment(lib, "Sample.lib") 

 :
 :

void TestMethod()
{
	// Sample.dll内の関数呼び出し
	SampleMethod();
}



…リンクエラーが表示されてしまう。。。

引用:

LNK2001: 外部シンボル""SampleMethod()"(?SampleMethod@@$$FYGFEEFJPAD@Z)"は未解決です。
LNK1120: 外部参照1が未解決です。



↑というエラーになってしまうので、
ヘッダファイルやLibが参照できているのかと、
ファイルを削除してみたら、
コンパイルエラーになったので
きちんとファイル自体は参照できている模様。


コード:
extern "C" xxxxx


これも追加して見たのですが、
"再定義されている"っていうことなので
関数も参照されているのかと。。。

他にこのリンクエラーの原因を検証する方法ってありますでしょうか?
何かありましたら、アドバイス、宜しくお願い致します。



…それで、本題(構造体の戻り値を取得)の方ですが、
パラメータなどで構造体のポインタを使用すれば、
できるのかなって思います。

ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-02-19 10:05
.defファイルのEXPORTS部分にSampleMethodを追加してみてください

コード:
EXPORTS
SampleMethod



優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-19 10:20
ゆうじゅんさん、ありがとうございます。

引用:

.defファイルのEXPORTS部分にSampleMethodを追加してみてください
コード:
 
EXPORTS
SampleMethod





Sample.dllを作成する方の".defファイル"ですよね。
コード:
LIBRARY Sample

CODE    PRELOAD MOVEABLE DISCARDABLE
DATA    PRELOAD MOVEABLE

EXPORTS
        SampleMethod                        @1
        SampleMethod2                       @2
     :



上記のようにやって、
LibファイルとDLLファイルを参照さしているのですが…。
ダメですね(^^;)
りばぁ
大ベテラン
会議室デビュー日: 2003/11/26
投稿数: 130
お住まい・勤務地: 愛知県
投稿日時: 2004-02-19 10:46
こんにちわ。

DLLの関数の戻り値を構造体にすることは、普通に可能ですけどねぇ・・・

たとえば、

コード:

DLL側

typedef struct TESTSTRUCT
{
int a;
int b;
} stTest;


stTest GetSTData()
{
stTest dat;

dat.a = 1;
dat.b = 2;

return dat;
}




コード:

DLL呼び出し側

stTest mydat;
mydat = GetSTData();




一応、注意としては、構造体の定義はDLL呼び出し側のほうにも必要です。
あとは、何も考えず作っても、大丈夫なはずです。
※DLLのヘッダーに構造体を定義してあれば、不要かもです^^;

エラーに関してですが、

引用:

VC++のメニュー[ツール]→[オプション]の
[プロジェクト]-[VC++ ディレクトリ]の
「ディレクトリを表示するプロジェクト:ライブラリ」で、
先ほどの「Lib」フォルダを追加。
同様に、「include」も追加する。



これが気になるのですが、プロジェクトにLibファイルを登録しているのですか?
もしそうなら、必要ないと思います。(includeは必要だと思いますが。)
※これって、もしかしてパスを通してるだけなのですかねぇ?であれば杞憂なのですが

[ メッセージ編集済み 編集者: りばぁ 編集日時 2004-02-19 10:52 ]

[ メッセージ編集済み 編集者: りばぁ 編集日時 2004-02-19 10:55 ]
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-02-19 10:52
LIBファイルをLIBフォルダから削除してみたらエラーが変わります?
「LIBファイルが見つかりません」とかに

大丈夫だとは思うのですがLIBファイルを参照できてないかもしれないので

あとLIBファイルが参照できているのであれば(エラーが変わっているのであれば)
VC5で作成したサンプルからそのLIBを使用できるか試してみたらどうでしょうか?

VC5のサンプルでも同じようなエラーが発生したらLIB側の問題
VC5で問題ないのであれば.NET側の問題
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-02-19 10:56
ほむらです。
見当違いなのことかもしれませんが気になったので
-----
C#側の構造体は値型というやつになっているようですけど
よいのですか?

C側からは先頭アドレスがかえってくるだけだと思うので
参照型というやつではないかと思うのですが。。。
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-02-19 11:14
>C側からは先頭アドレスがかえってくるだけだと思うので
↓のコードが成り立つという事は値が返ってきてることなので
やっぱりC#側も値型でいいと思いますよ

コード:
typedef struct TESTSTRUCT
{
	int a;
	int b;
} stTest;

stTest GetSTData()
{
	stTest dat;

	dat.a = 1;
	dat.b = 2;

	return dat;
}

りばぁ
大ベテラン
会議室デビュー日: 2003/11/26
投稿数: 130
お住まい・勤務地: 愛知県
投稿日時: 2004-02-19 11:13
引用:

ほむらさんの書き込み (2004-02-19 10:56) より:
C#側の構造体は値型というやつになっているようですけど
よいのですか?

C側からは先頭アドレスがかえってくるだけだと思うので
参照型というやつではないかと思うのですが。。。



えと、C#とC++(VC++)の違いは良く知りませんが。
変数が生きている期間が重要で、たとえば、

コード:

char* TestFunc()
{
char c;

c = 'a';

return &c;
}


なんてことをすると、この関数を抜けた時点で変数cはきえてしまうので、
'a'を取得することは出来ません。(この例良くなさげですね・・・)
呼び出し側で確保したメモリに対しての読み書きをする場合は良いのですが、
戻り値で、値渡しをするか、メモリ渡しをするかは、重要なのお気を付けください^^;

ちなみに、ぼくの前回の構造体を戻り値にしている例では、値を渡しています。
この場合、return時に呼び元側で確保してあるメモリに値を書き込むので、
戻り値を受け取る事が出来ます。

[追加]
をを、ぼくが一生懸命書いている間に、ゆうじゅんさんのフォロー(?)が。

えっと、突っ込まれる人がいるかもしれんませんが。
C++では値を渡すかアドレスを渡すかは、プログラマーが決めることなので、

void SetData(int a);<-値渡し
void SetData(int *a);<-ポインタ渡し
void SetData(int &a);<-参照渡し

てなると思うのですが。
もしや、話がかみ合ってなくて、そういうことを言ってるんじゃない??
[/追加]

[ メッセージ編集済み 編集者: りばぁ 編集日時 2004-02-19 11:19 ]

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