複数の特電Spartan-6ボードを開く64bit版DLL
あるお客様から
「64bit版アプリから、複数の特電Spartan-6ボードを同時に使用したい。」
というご依頼をいただきました。

複数の特電Spartan-6ボードを開くためのドライバとDLLは、必要とされるお客様に32bit版で提供してきたのですが、どうしても64bit版が必要とのことでした。
WOW64があるから32bit版のDLLでできるのではないかと思っていたのですが、MFCを使うアプリではだめなのですね。きっと。
そこで、「複数のボードを同時に開くDLL」を作ろいとしたのですが、VisualC++でのDLLの作り方を忘れていたため、いろいろとはまりました。
まずは、DLLの作り方を備忘録として書いておきます。
DLLで関数をexportするには、関数の宣言の前に__declspec(dllexport)を付けるか、その関数の名前をDEFファイルに書いておきます。私は__declspec(dllexport)のほうが好きです。
descspecを使う場合は、
__declspec(dllexport) int WINAPI hoge();
のようにして関数を宣言します。
descspecを使わない(DEFファイル)の場合は、
int WINAPI hoge();
のようにします。
WINAPIは、DLLからエクスポートする関数にはこれを付けます。引数が右から順にスタックに詰められるそうです。
DEFファイルを使ってエクスポートする関数を列挙する場合、「DEFファイル」は、
LIBRARY "tkusb" EXPORTS USBGetMaxInstance @1 USBGetBoardInfo @2 USBSetBoardUserId @3 USBGetDriverVersion @4 USBGetFirmwareVersion @5 USBReadEEPROM @6 USBWriteEEPROM @7 ・・・
のように書きます。@数字は、序数といってDLLの中に入っている関数を示す数字です。
自分の過去のプログラムを見ていて、以下のような書き方をする場合もありました。
LIBRARY "tkusb" EXPORTS USBGetMaxInstance@0 = USBGetMaxInstance @1 USBGetBoardInfo@4 = USBGetBoardInfo @2 USBSetBoardUserId@4 = USBSetBoardUserId @3 USBGetDriverVersion@0 = USBGetDriverVersion @4 USBGetFirmwareVersion@0 = USBGetFirmwareVersion @5 USBReadEEPROM@12 = USBReadEEPROM @6 USBWriteEEPROM@12 = USBWriteEEPROM @7 ・・・
「関数名@数字 = 関数名 @数字」という形になっていますが、これはBorlandC++で作ったDLLをVisualC++で使うためのインポートライブラリを生成するための書き方です。@数字は、その関数の引数の総バイト数を表すようです。この形式のDEFファイルの書き方でVisualC++でビルドすると、USBGetMaxInstance@0という関数名の関数として扱われてしまうようで、リンクできません。
まぁ、この形式のDEFファイルを作るには人間が引数を数えなければいけないから、ミスも入るでしょう。DLLはVisualC++で作るべきだと思います。
さて、これでDLLを作る準備ができたわけですが、VisualStudop2010 Expressで64bit版のDLLを作る方法は、過去の記事「Visual Studio Expressで64bit版DLLを作成してみる」
https://nahitafu.cocolog-nifty.com/nahitafu/2014/04/visual-studio-e.html
に書いてありました。
過去の記事に書いてあった方法でビルドはできました。しかし、実行すると不正な処理して止まってしまいます。
どうやら、その原因はCyAPIをOpenしていることが原因でした。
64bit版のCyAPIのバージョンが古いためか、
CCyUSBDevice hCyApi= new CCyUSBDevice(); delete hCyApi;
だけで不正な処理をして止まってしまうようです。結局、cyusb.sysとcyapi.dllを使わずに、ezusb.sysベースのデバイスドライバを使うようにしたところ、止まらずに起動できるようになりました。
自分の過去の日記を読んでみると、
「Spartan-6ボードのWindows7 64bit対応」
https://nahitafu.cocolog-nifty.com/nahitafu/2011/02/21/index.html
に書いていたのですが、2011年ごろに一時期EZ-USB FX2LPをCyAPIでアクセスしようとして開発していたけれども、速度の問題などで、結局、古いezusb.sysを64bit版でコンパイルすることにしたようでした。
マルチボード対応のDLLを使ったアプリは、
#include <stdio.h>#include "tkusb.h" int main() { TKUSB_HANDLE h = USBOpenExByID(0); printf("Handle = %x\n",h); if(!h) return 0; USBSetSmajModeEx(h,0); // Smajモードを解除し、通常動作モードへ unsigned char buffer[256]; for(int i=0;i<256;i++) buffer[i] = i; USBWriteDataEx(h,buffer,256,1); // BRAMに256バイト書き込み memset(buffer,0,256); USBReadDataEx(h,buffer,256,1); // BRAMから256バイト読み出し for(int i=0;i<256;i++) { printf("%x ",buffer[i]); } USBCloseEx(h); return 0; }
という感じになります。最初のUSBOpenExByIDという関数の引数を変えると、USBにつながった複数のSpartan-6ボードを開けるという仕組みです。
もちろん、PCにつながっている特電Spartan-6ボードの総数を調べる関数もあり、ボード上のEEPROMに書かれた小さなデータを読み出す機能もあるので、複数のボードを区別して開くこともできるというわけです。
もう数日テストしてみて、問題がなければリリースしたいと思います。
| 固定リンク


コメント