none
トラッキング参照 RRS feed

  • 質問

  • 重複しているかもしれませんが見つける事が出来なかったもので
    質問させていただきます。

    .NET C++/CLIでトラッキング参照をうまく取得できません。
    お力添えお願い致します。

    現在
    VC++6.0で書かれたソースとヘッダ(下記)
    ----------------------
    header.h

    #define LJ_HANDLE long
    #define LJ_ERROR long

    #ifdef  __cplusplus
    extern "C"
    {
    #endif
     :
    LJ_ERROR _stdcall Gett(LJ_HANDLE Handle, long IType, long Channel, double *pValue);
     :
    }

    ----------------------
    test.cpp

    int main(){

    LJ_HANDLE Handle=0;
    double Value=0, Data=0;
    long IType=0, Channel=0;
     :
    Errorcode = Get(Handle, &IType, &Channel, &Value);
    Data=Value;
     :
    }
    ----------------------
    はvc++2008でコンパイルリンクしたコンソールエディタは
    正常にDataにValueの値を取得出来ています。

    これを
    .NET C++/CLI VC2008 でヘッダはそのままでソース書きなおし
    イベント内に記述させると

    トラッキング参照方法が異なり
    上記のままではコンパイルエラーを起こしてしまいます。

    Errorcode = Get(Handle, &IType, &Channel, &Value);
    をC++/CLIで書き変えるにはどのようにしたらよいでしょうか?

    現在
    interior_ptr<long*> pIType = &IType;
    Errorcode = Get(Handle, IType, &Channel, &Value);
    書いたのですが
    error C2664: 'Get' : 2 番目の引数を 'cli::interior_ptr<Type>' から 'long' に変換できません。

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

    2010年2月23日 4:35

回答

  • LJ_ERROR _stdcall Gett(LJ_HANDLE Handle, long IType, long Channel, double *pValue);


    LJ_HANDLE Handle=0;
    double Value=0, Data=0;
    long IType=0, Channel=0;
     :
    Errorcode = Get(Handle, &IType, &Channel, &Value);

    という記述は間違っていませんか?
    第2・3引数はポインタを欲していないので & はいらないはずです。
    (Errorcode = Get(Handle, IType, Channel, &Value);でいいはず)
    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 4:48
  • ローカル変数のdoubleの変数であれば、interior_ptrはいらないのではないかなぁと。

    lngErrorcode = GetResult(lngHandle, lngIOType, lngChannel, &Value);

    # マネージ⇔アンマネージなのでinterior_ptrではなくpin_ptrではないかと。

    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 5:24
  • これでコンパイルすると
    error C2664: 'Get' : 4 番目の引数を 'cli::interior_ptr<Type>' から 'double *' に変換できません
    となります。
    ということは、Valueはマネージドクラスのメンバか何かでしょうか?
    そうであれば前述通りpin_ptrを使ってください。

    適当なサンプルコード
    void Set10_UP(int* p) { *p = 10; }
    void Set20_IP(interior_ptr<int> p) { *p = 20;}
    
    ref struct moge { int n_; };
    
    int main()
    {
    	int n;
    	Set10_UP(&n);
    	System::Console::WriteLine(L"{0}", n);
    
    	Set20_IP(&n);
    	System::Console::WriteLine(L"{0}", n);
    
    	moge m;
    	pin_ptr<int> p = &m.n_;
    	//Set10_UP(&m.n_);	// C2664
    	Set10_UP(p);
    	System::Console::WriteLine(L"{0}", m.n_);
    
    	Set20_IP(&m.n_);
    	System::Console::WriteLine(L"{0}", m.n_);
    
    	return 0;
    }

    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 5:43
  • header.h内のGetという関数の定義はDLLか何かでしてあるのでしょうか?
    (Getという関数は一般的なものではないと思われ。独自に作ったものであると。)
    静的リンクであれば作成したDLLに対応するlibファイルを#pragma comment(lib, "xxxx")なり、プロパティのリンカの入力なりで指定します。

    libファイルがなければ、動的リンクになります。
    Win32 APIのLoadLibray+GetProcAddressあたりでゴリゴリ組むか、
    いっそのこと、DllImportで組むかのどちらかでしょう。


    しかしながら、
    >はvc++2008でコンパイルリンクしたコンソールエディタは
    >正常にDataにValueの値を取得出来ています。
    ということなので、静的リンクで行けるような。
    設定を確認してみてはどうでしょうか?
    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 7:25
  • vcprojファイルに直接書き込んだらうまく行きました。

    直接書き込まなくても、UIから設定できるはずです。

    リンクするモジュール(obj、lib等)は、プロジェクトのプロパティを開いて、リンカの入力、追加の依存ファイルに「ファイル名」を記述します。
    ライブラリのディレクトリがIDEのディレクトリ設定にない場合は、構成プロパティ-->リンカ-->全般-->追加のライブラリ ディレクトリに
    「ディレクトリのパス」を入力します。追加の依存ファイルにフルパスで入力しても良いと思いますけれど、
    構成上はディレクトリパスとファイル名を分けて入力できるようになっています。
    これはリンク対象のライブラリが複数あってそのディレクトリパスを指定する必要がある場合に一回だけディレクトリパスを入れておけば、
    ファイル名の方にはパスをつけなくて良いわけですね。

    個人的にはライブラリのディレクトリをIDEのディレクトリの設定にどんどん追加するのはあまり感心しないと思っているので
    そのプロジェクトにしか必要ないライブラリのパスはプロジェクトの設定の方でやった方が良いと思います。
    そうすれば、プロジェクトの設定を確認する事で特別にリンクしているライブラリを容易に確認できます。

    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2010年2月25日 4:57

すべての返信

  • LJ_ERROR _stdcall Gett(LJ_HANDLE Handle, long IType, long Channel, double *pValue);


    LJ_HANDLE Handle=0;
    double Value=0, Data=0;
    long IType=0, Channel=0;
     :
    Errorcode = Get(Handle, &IType, &Channel, &Value);

    という記述は間違っていませんか?
    第2・3引数はポインタを欲していないので & はいらないはずです。
    (Errorcode = Get(Handle, IType, Channel, &Value);でいいはず)
    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 4:48
  • LJ_ERROR _stdcall Gett(LJ_HANDLE Handle, long IType, long Channel, double *pValue);


    LJ_HANDLE Handle=0;
    double Value=0, Data=0;
    long IType=0, Channel=0;
     :
    Errorcode = Get(Handle, &IType, &Channel, &Value);

    という記述は間違っていませんか?
    第2・3引数はポインタを欲していないので & はいらないはずです。
    (Errorcode = Get(Handle, IType, Channel, &Value);でいいはず)
    わんくま同盟[http://blogs.wankuma.com/blue/]
    ありがとうございます。
    間違っていましたね。
    Errorcode = Get(Handle, IType, Channel, &Value);
    でコンパイルすると

    error C2664: 'Get' : 4 番目の引数を 'cli::interior_ptr<Type>' から 'double *' に変換できません
    となります。

    そこで、
    interior_ptr<double*> pValue = &Value;
    lngErrorcode = GetResult(lngHandle, lngIOType, lngChannel, plValue );

    とすると
    error C2440: '初期化中' : 'cli::interior_ptr<Type>' から 'cli::interior_ptr<Type>' に変換できません。
    となってしまいます。
    2010年2月23日 5:09
  • ローカル変数のdoubleの変数であれば、interior_ptrはいらないのではないかなぁと。

    lngErrorcode = GetResult(lngHandle, lngIOType, lngChannel, &Value);

    # マネージ⇔アンマネージなのでinterior_ptrではなくpin_ptrではないかと。

    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 5:24
  • 重ね重ねすみませんまた記載ミスです。m(_ _)m
    lngErrorcode = GetResult(lngHandle, lngIOType, lngChannel, &Value);
    下が正解です。
    Errorcode = Get(Handle, IType, Channel, &Value);

    これでコンパイルすると
    error C2664: 'Get' : 4 番目の引数を 'cli::interior_ptr<Type>' から 'double *' に変換できません
    となります。

    なので
    interior_ptr<double*> pValue = &Value;
    lngErrorcode = GetResult(lngHandle, lngIOType, lngChannel, plValue );
    としたのですが
    error C2440: '初期化中' : 'cli::interior_ptr<Type>' から 'cli::interior_ptr<Type>' に変換できません。
    となってしまい 型がそもそも違っているのか古いC言語のヘッダだからなのだろうか。
    途方に暮れています。
    2010年2月23日 5:39
  • これでコンパイルすると
    error C2664: 'Get' : 4 番目の引数を 'cli::interior_ptr<Type>' から 'double *' に変換できません
    となります。
    ということは、Valueはマネージドクラスのメンバか何かでしょうか?
    そうであれば前述通りpin_ptrを使ってください。

    適当なサンプルコード
    void Set10_UP(int* p) { *p = 10; }
    void Set20_IP(interior_ptr<int> p) { *p = 20;}
    
    ref struct moge { int n_; };
    
    int main()
    {
    	int n;
    	Set10_UP(&n);
    	System::Console::WriteLine(L"{0}", n);
    
    	Set20_IP(&n);
    	System::Console::WriteLine(L"{0}", n);
    
    	moge m;
    	pin_ptr<int> p = &m.n_;
    	//Set10_UP(&m.n_);	// C2664
    	Set10_UP(p);
    	System::Console::WriteLine(L"{0}", m.n_);
    
    	Set20_IP(&m.n_);
    	System::Console::WriteLine(L"{0}", m.n_);
    
    	return 0;
    }

    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 5:43
  • ありがとうございます。
    サンプルを元に以下のように書いてみました。

    Form1.h
    -----------------------------

    #include "header.h"

    namespace SerialCommSample {

     public ref class Form1 : public System::Windows::Forms::Form
     {
     public:
      Form1(void)
      {
       InitializeComponent();
       IType=0, Channel=0, Handle=0;  :
      :

     double Value;
     LJ_ERROR Errorcode;
     LJ_HANDLE Handle;

         private: System::Void buttonConnect_Click(System::Object^  sender, System::EventArgs^  e) {

           moge mzz;
           pin_ptr<double> pdblValue = &mzz.strctU3Value_;
           lngErrorcode = GetResult(lngHandle, lngIOType, lngChannel, pdblValue );
           Data=mzz.strctU3Value_;
         }
         ref struct moge { double strctU3Value_; };
      };
    }

    でコンパイルしたところ
    コンパイルはOKでした。

    非常に助かりました。

    しかし
    リンクで以下のように出力されてしまいました。

    SerialCommSample.obj : error LNK2028: 未解決のトークン (0A00003C) "extern "C" long __stdcall Get(long,long,long,double *)" (?Get@@$$J216YGJJJJPAN@Z) が関数 "private: void __clrcall SerialCommSample::Form1::serialPort_DataReceived(class System::Object ^,class System::IO::Ports::SerialDataReceivedEventArgs ^)" (?serialPort_DataReceived@Form1@SerialCommSample@@$$FA$AAMXP$AAVObject@System@@P$AAVSerialDataReceivedEventArgs@Ports@IO@4@@Z) で参照されました。

    SerialCommSample.obj : error LNK2019: 未解決の外部シンボル "extern "C" long __stdcall Get(long,long,long,double *)" (?GetResult@@$$J216YGJJJJPAN@Z) が関数 "private: void __clrcall SerialCommSample::Form1::serialPort_DataReceived(class System::Object ^,class System::IO::Ports::SerialDataReceivedEventArgs ^)" (?serialPort_DataReceived@Form1@SerialCommSample@@$$FA$AAMXP$AAVObject@System@@P$AAVSerialDataReceivedEventArgs@Ports@IO@4@@Z) で参照されました。

    等、どしゃっとでてしまいました。
    そこでググってみると


    #pragma comment( lib, "GDI32.lib" )
    #pragma comment( lib, "USER32.lib" )
    が読み込まれていない為?とのことでしたので
    CPPファイルに記載してみたが、変わらずでした。

    他の解決方法

    プロジェクトのプロパティー → 構成プロパティーのMFC使用の欄を"標準Windowsライブラリを使用する"に変える。
    プロジェクトのプロパティー →C++ →コード生成→ランタイムライブラリの欄を"マルチスレッドデバックDLL(/MDd)"に変える。
    ------>既に上記の設定になっている。

    プロジェクトの プロパティ ページ の リンカ の 入力 の 「継承の値」の下の「親またはプロジェクトの既定値から継承」のチェックをONする!!
    ------>継承の値が無い(;; なんで?
       で、追加の依存ファイルに”親またはプロジェクトの既定値から継承”をチェック
       が....エラー変わらず。

    困ってしまいました。
    2010年2月23日 7:10
  • header.h内のGetという関数の定義はDLLか何かでしてあるのでしょうか?
    (Getという関数は一般的なものではないと思われ。独自に作ったものであると。)
    静的リンクであれば作成したDLLに対応するlibファイルを#pragma comment(lib, "xxxx")なり、プロパティのリンカの入力なりで指定します。

    libファイルがなければ、動的リンクになります。
    Win32 APIのLoadLibray+GetProcAddressあたりでゴリゴリ組むか、
    いっそのこと、DllImportで組むかのどちらかでしょう。


    しかしながら、
    >はvc++2008でコンパイルリンクしたコンソールエディタは
    >正常にDataにValueの値を取得出来ています。
    ということなので、静的リンクで行けるような。
    設定を確認してみてはどうでしょうか?
    わんくま同盟[http://blogs.wankuma.com/blue/]
    2010年2月23日 7:25
  • USBのAD変換データロガーで、付属のドライバはインストールしてある為
    header内の関数が使えている状況だと思います。

    libファイルがあるので

    #pragma comment( lib, "labjackud.lib" )

    として取り込んでも

    >LINK : fatal error LNK1104: ファイル 'labjackud.lib' を開くことができません。

    と表示されてしまい、labjackud.libフルパスでlibファイルを指定してあげても同じでした。

    設定の確認なのですが、何処を見直したらよいのでしょうか?
    使い始めてまだ間もなく、いろいろ探してはいるものの今一つ分からないでいます。
    現在
    構成プロパティ-->リンカ-->全般-->追加のライブラリ ディレクトリ
    にlabjackud.lib をフルパスで入力していますが、エラーをなくすことが出来ないでいます。

    2010年2月23日 9:31
  • vcprojファイルに直接書き込んだらうまく行きました。

      :
      <File
       RelativePath="C:\Program Files\LabJack\Drivers\labjackud.lib"
       >
      </File>
     </Files>
     <Globals>
     </Globals>
    </VisualStudioProject>


    ありがとうございました。
    後は実際にプログラムが期待通りの値を取得できるかの確認となります。
    2010年2月23日 9:55
  • データ取得も出来ました。
    これで今日は家に帰って寝れます。
    2010年2月23日 13:29
  • vcprojファイルに直接書き込んだらうまく行きました。

    直接書き込まなくても、UIから設定できるはずです。

    リンクするモジュール(obj、lib等)は、プロジェクトのプロパティを開いて、リンカの入力、追加の依存ファイルに「ファイル名」を記述します。
    ライブラリのディレクトリがIDEのディレクトリ設定にない場合は、構成プロパティ-->リンカ-->全般-->追加のライブラリ ディレクトリに
    「ディレクトリのパス」を入力します。追加の依存ファイルにフルパスで入力しても良いと思いますけれど、
    構成上はディレクトリパスとファイル名を分けて入力できるようになっています。
    これはリンク対象のライブラリが複数あってそのディレクトリパスを指定する必要がある場合に一回だけディレクトリパスを入れておけば、
    ファイル名の方にはパスをつけなくて良いわけですね。

    個人的にはライブラリのディレクトリをIDEのディレクトリの設定にどんどん追加するのはあまり感心しないと思っているので
    そのプロジェクトにしか必要ないライブラリのパスはプロジェクトの設定の方でやった方が良いと思います。
    そうすれば、プロジェクトの設定を確認する事で特別にリンクしているライブラリを容易に確認できます。

    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2010年2月25日 4:57