• ベストアンサー

Chasen.dllをBCB5で使う方法を教えてください(DLLの使い方)

形態素解析ツールのChasen Win32版に付属しているchasen.dllを自作のプログラムから呼び出したいと思っています。 ・茶筅 http://chasen.aist-nara.ac.jp/index.html.ja ですが、DLLを使ったことがないのでよくわからずもう何日も困っています。 ヘッダで、まずDLL付属のヘッダー(下記参考資料)をインクルードして、 #include "chadll.h" 自作プログラムのソースで、 HINSTANCE chasenDLL = LoadLibrary("chasen.dll"); でライブラリをロードして、 char *myanalyze = (char *)GetProcAddress(chasenDLL,"analyze"); で関数analyzeを取り出していますが、 analyze()を実際に使うとシンボルの未解決エラーでコンパイルできません。 このDLLはBCBでは使えないのでしょうか。 ---------------------参考資料:DLL付属のサンプルソース /* * dlltest.c - ChaSen dll test program * * Copyright (C) 2000 Nara Institute of Science and Technology * * Author: H.Matsuda <horosi-m@is.aist-nara.ac.jp>, Sep. 2000 */ #include <stdio.h> #include "chadll.h" int main( int argc, char** argv ) { char input[10000] = "これは形態素解析のテストです。"; set_argument_parameters( argc, argv ); printf( "%s", analyze( input ) ); } ---------------------参考資料:DLL付属のヘッダーファイル /* * chasendll.h - ChaSen dll header * * Copyright (C) 2000 Nara Institute of Science and Technology * * Author: H.Matsuda <horosi-m@is.aist-nara.ac.jp>, Sep. 2000 */ __declspec( dllexport ) int set_argument_parameters( int argc, char** argv ); __declspec( dllexport ) char* analyze( char* input );

質問者が選んだベストアンサー

  • ベストアンサー
  • selenity
  • ベストアンサー率41% (324/772)
回答No.2

Chasenを使い前にDLLの使い方を勉強しましょう。 DLLの利用の仕方でStatic LinkとDynamic Linkの2通り があることをご存じですか? このサンプルはStatic Linkの例です。 したがってBCB5用のchasen.libというファイルが 必要になります。おそらく付属のlibファイルは VC用でしょう。 implib.exeを使ったような気がします、、、 Dynamic Linkを使うのであれば、 typedef char* WINAPI (*TAnalyze)(char*); TAnalyze analyze; HINSTANCE cDLL; cDLL = LoadLibrary("chasen.dll"); myanalyze = (TAnalyze)GetProcAddress(cDLL,"analyze"); の様に記述する必要があります。 注意としてGetProcAddress(cDLL,"xxxxxx"); のxxxxxxの部分は状況に応じて_xxxxxxとする必要が あるかもしれません。

Blogger
質問者

お礼

ソースまで示していただき丁寧なご回答、本当にありがとうございました。教えていただいたコードを理解するため、DLLやポインタの参考書をひっくり返して調べておりまして御礼おくれてすみません。 なんとかおっしゃる方法で、KAKASIのDLLライブラリを動的に読み込み、動かすことができました。Chasenの方はライブラリのロードはできたのですが何らかの(chasenの使い方)の問題でまだうまく動いておりません。analyzeなど読み込んだ関数を使う場面でEAccessViolationのエラーがでてしまうのです。 とりあえずはKAKASIが動きましたのでやりたいことはできそうなのですが、Chasenが動かない状況も、勉強がてら解決したいので、もう少しがんばってみようと思います。 本当にありがとうございました!。

Blogger
質問者

補足

同じことをしたい方が後にいるときのために私の現状のメモを残させてください。 以下のようにChasen.dllを呼び出しました。すると関数を使おうとするところで、EAccessViolationが発生します。 ----------------------------------------------- void __fastcall TLogoAppForm::BitBtn1Click(TObject *Sender) { typedef char* WINAPI (*TAnalyze)(char*); TAnalyze analyze; typedef int WINAPI (*TSetArgParm)(int argc,char** argv); TSetArgParm set_argument_parameters; char *argv[] = {"-a", "-r"}; HINSTANCE cDLL; char *input = "解析したい文字列"; cDLL = LoadLibrary("chasen.dll"); if (cDLL) RichEdit1->Lines->Add("LoadDLL成功"); analyze = (TAnalyze)GetProcAddress(cDLL,"analyze"); if (analyze) RichEdit1->Lines->Add("analyze関数取得成功"); set_argument_parameters = (TSetArgParm)GetProcAddress(cDLL,"set_argument_parameters"); if (set_argument_parameters) RichEdit1->Lines->Add("set_argument_parameters関数取得成功"); AnsiString StrTest; StrTest = analyze(input); FreeLibrary(cDLL);

その他の回答 (1)

  • jun_l
  • ベストアンサー率18% (4/22)
回答No.1

DLLにLIBファイルは付属していたでしょうか?(拡張子*.LIB) もし付属していたならば、リンクファイルに追加してください。 (VC用と書いてあったら無理ですね(笑)) もしVC用のLIBでしたら、LoadLibrary()とGetProcAdress()を使うしかないです。 これならばどのコンパイラでも使用できるはずです。 というか、先ほどのLIBファイルを使用できたとしても、こちらの方法で動的にリンクするほうがいいです。

Blogger
質問者

お礼

質問者です。ご回答ありがとうございます。 LIBファイルはIMPLIBでBCB版を作成してみました。その上で、プロジェクトにLIBをファイルを追加したのですが、やはり結果は同じで外部シンボルの未解決によって、だめでした。 とりあえずご指摘のように、動的リンクしかなさそうなのでそちらで試してみたいと思います。

関連するQ&A

  • 茶筅を使いたい!

    茶筅を使って形態素解析を行いたいと思っています。 使う言語はC++です。 環境はborland C++ 5.5です。 サンプルプログラムを実行するのですが、 Error: 外部シンボル '_set_argument_parameters' が未解決(C:\PROGRAM FILES\CHASEN21\DLL\DLLTEST.OBJ が参照) Error: 外部シンボル '_analyze' が未解決(C:\PROGRAM FILES\CHASEN21\DLL\DLLTEST.OBJ が参照) というエラーがでます。 環境設定で、chadll.hのある場所まで設定しています。 (この辺の意味が全然わかりませんが) dllとかlibとかに疎いので、全然進めません。 どのようにすればうまく動かすことができますか?? サンプルプログラム #include <stdio.h> #include "chadll.h" int main(int argc,char** argv) { char input[10000] = "これは形態素解析のテストです。"; set_argument_parameters(argc,argv); printf( "%s", analyze( input ) ); return 0; }

  • C言語のシェルプログラミングの課題が分かりません。

    C言語のシェルプログラミングを作れという課題で、以下のように作ったんですが、実行して何度かコマンドを入力した後、exitによって一発で終わらせることができません。どのように書き換えればいいか教えて下さい。 また、他にも書き換えた方がよいと思えるところがあったら是非教えて下さいm(_ _)m #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #include <sys/types.h> #include MAX_ARGS 10 #include MAX_LEN 100 extern char **environ; void child(int argc, char *argv[MAX_ARGS]); int main(void){ int argc, n = 0; int status; char input[MAX_LEN], *argv[MAX_ARGS], *cp; const char *delim = "\t\n"; while (1){ ++n; printf("$ "); fflush(stdout); if(fgets(input, sizeof(input), stdin) == NULL){ break; } cp = input; for(argc = 0; argc < MAX_ARGS; argc++){ if((argv[argc] = strtok(cp, delim)) == NULL) break; cp = NULL; } if(strcmp(argv[0], "exit") == 0){ exit(0); } pid_t pid = fork(); if(pid == -1){ perror("fork"); exit(1); }else if(pid == 0){ child(argc, argv); }else{ wait(&status); } } return 0; } void child(int argc, char *argv[MAX_ARGS]{ execvp(argv[0], argv); }

  • 二行目の*の意味を教えてください。

    #include <stdio.h> int main(int argc, char *argv[]) { int i; for ( i = 0; i < argc; i++ ){ printf("argv[%d]=%s\n", i, argv[i]); } return argc; }  以上プログラムで、二行目の*の意味を教えてくさい。  6行目のargvには*が付いていません!?  よろしくお願いします。

  • C#からDLLの呼び出し方

    visual studio 2008 express edition C#3.5 を使用しています。 http://www.hata.cc/docs/wlinee/1.html を参考にC++からではMySub関数を呼び出すことができたのですが、 C#から呼び出そうと次のように記述したのですが、 [System.Runtime.InteropServices.DllImport("a.dll")] extern int WINAPI MySub(int a, int b); 書き終わったときに、MySubの下に赤線がでて「;が必要です」 というエラーが出てしまいます・・・ たぶん「WINAPI」が認識されてないと思うのですが、 どのように記述すればよいのでしょうか? ~C++での記述~ [dllcall.cpp] #include "stdafx.h" #include <windows.h> #include <conio.h>  // getch( ) を使用するのに必要 extern int WINAPI MySub(int a, int b); int _tmain(int argc, _TCHAR* argv[]) { int c; c=MySub(9, 3); printf("ans=%d\n",c); getch();// キーが押されるまで待つ return 0; } [a.cpp] __declspec(dllexport)int WINAPI MySub(int a, int b) { return a-b; }

  • DLLの関数呼び出しで引数があるとフリーズしてしまう。

    はじめまして、C言語勉強中の初心者です。 現在、DLLに定義されている関数を呼び出すことを試していますが、うまくいかないので質問させて頂きました。 DLLには2つの関数が定義されています。  1.void Hello()  2.void HelloEx(char *pval); 1の関数を呼び出す場合は異常なく終了するのですが、2の関数を呼び出すと、フリーズしてしまいます。 フリーズする原因が分からないので、教えて頂ければと思います。 以下にソースを掲載します。 因みにコンパイラはBCC5.5.1を使用しています。 ***************************************************** DLL(Hello.c) [bcc32 -WD Hello.c] ***************************************************** #include <windows.h> #include <stdio.h> __declspec(dllexport) void CALLBACK Hello(void) { printf("Hello!\n"); } __declspec(dllexport) void CALLBACK HelloEx(char *pVal) { printf("Hello!%s\n", pVal); } ***************************************************** EXE(HelloTest.c)[bcc32 -L HelloTest.c] ***************************************************** #include <windows.h> #include <stdio.h> typedef void (*Hello)(void); typedef void (*HelloEx)(char*); int main(void) { HMODULE hMod; Hello func; HelloEx funcEx; hMod = LoadLibrary( "Hello.dll" ); if(!hMod) return FALSE; func = (Hello)GetProcAddress( hMod, "Hello"); if(!func) return FALSE; funcEx = (HelloEx)GetProcAddress( hMod, "HelloEx"); if(!funcEx) return FALSE; func(); funcEx("World"); FreeLibrary(hMod); return 0; } *********************************************** 以上

  • DLL作成時、defファイルを使いたくない

    また質問させて下さい。 Visual Studio2005でDLLを使ったプログラムを作ろうとしています。 defファイルを利用すると、そのDLLファイルを作成できるのですが、 __declspec(dllexport)を利用すると、DLLファイルのその関数を読めなくなってしまいます。 なぜでしょうか? 下記は、MFCで、dll_test7というプロジェクトを作り、そのdll_test7.hのコードのすぐ下に その関数を書きました。(これがダメだと思うのですが…) //●Visual Studioのプロジェクト作成で、生成される部分 // dll_test7.h : dll_test7.DLL のメイン ヘッダー ファイル // #pragma once __declspec(dllexport) void __cdecl test0(void); #ifndef __AFXWIN_H__ #error "PCH に対してこのファイルをインクルードする前に 'stdafx.h' をインクルードしてください" #endif #include "resource.h" // メイン シンボル // Cdll_test7App // このクラスの実装に関しては dll_test7.cpp を参照してください。 // class Cdll_test7App : public CWinApp { public: Cdll_test7App(); // オーバーライド public: virtual BOOL InitInstance(); DECLARE_MESSAGE_MAP() }; //■作成した関数 __declspec(dllexport) void __cdecl test0(void) { CString cs; cs="aa"; ::AfxMessageBox(cs); } 上記は、defファイルを利用するとこの関数を呼び出せます。 以上、どうぞよろしくお願い致します。

  • VC2005のDLLを6.0で呼び出すには

    VC 2005 Pro Editionで作ったライブラリ(ヘッダ、lib、dll)を頂きました。    頂いたDLLの形式は定義ファイル.defを使わない形式、declspec(dllexport)を使う形式の方です。  呼び出し側はVC6.0EnterPrize(SDK)を使います。 (諸事情により6.0以上にUPすることは不可能)     まず、静的リンクをし、関数を呼び出してみました。  (設定のリンクよりlibをリンクさせ、ヘッダをインクルードして)  すると以下のメッセージが出てしまいます。 リンク中... Dialog1.obj : error LNK2001: 外部シンボル ""__declspec(dllimport) void __cdecl Init(unsigned char *,unsigned char *,unsigned char *,unsigned char *)" (__imp_?Init_Card@@YAXPAE000@Z)" は未解決です Debug/CardMake.exe : fatal error LNK1120: 外部参照 1 が未解決です 。 link.exe の実行エラー    色々やってみましたが、このエラーから回避できませんでした。  ヘッダ自体に #ifdef _USRDLL #define DLL_PORT __declspec(dllexport) #else #define DLL_PORT __declspec(dllimport) #endif    の宣言があるので、別に特別なことをしなくても、大丈夫そうなのですが、何故か出来ません。  次に動的リンクを行っていました。  するとLoadLibraryでエラーになり、GetLastErrrorで14001(エラーメッセージはつかめず)が返ってきました。 (色々調べたところ定義ファイルがないと動的リンクはできないようですね)    というわけでにっちもさっちも行かなくなった状況です。  そこでご質問です。 (1)定義ファイルを使わない形式のライブラリ(暗示的に定義されているもの)はどのように呼び出させばよいでしょうか? (2)2005のライブラリを6.0から呼び出すことは可能ですか?  また呼び出す方法は?  すいませんがご回答をお願いします。

  • Cで自作したDLLをへC#から文字配列を渡したい

    CでDLLを自作したのですが、その引数にchar**型があるのですが、C#から使用するときにどの型の変数を渡せばいいのかわかりません。 色々と調べていくつか同じような事例があったのですが、うまくいきません。 Cで作ったDLLは __declspec(dllexport) int DetectComPorts(LPWORD ComPortTable, int ComPortMax, char **ComPortDesc) です。この中で「char **ComPortDesc」が問題です。 Cで書いたプログラムからはこのDLLが使用できることを確認しています。 Cの場合はchar**型の適当な変数を作ってmallocでメモリ確保してこの関数に渡して実行するとちゃんとアドレスに目的の文字列が格納されて帰ってきます。 よろしくお願いします

  • C言語でコマンドラインの引数について。

    コマンドラインで引数をわたす基本的なプログラムは main(int argc,char *argv[]){....] ですよね。 今回実行時に、 >実行ファイル名 123 + 233 といれたら、123+233を計算してくれるプログラムを作ろうとしています。 その場合、main(int argc,int *argv[]){} としたら、argv[1]に123が入って、argv[2]に+が入って、argv[3]に233が、入るというわけではないんでしょうか? とりあえず、確認で #include<stdio.h> main(int argc,int *argv[]) { printf("%d\n%d\n",argv[1],argv[3]); } としてみたんですが、実行結果は、とても長い数字がでてきてきました。 なにがいけないのか教えてください。 お願いします。 あとWindows MEでVC++6を使ってます。

  • strcmp,strcpy

    a.outの後で入力した文字列を比較するコードでの質問です。 #include<stdio.h> #include<string.h> int mystrcmp(???){ ??? } int main(int argc,char*argv[]){ printf(???); exit(0); } ???の所をどう書けばいいか分かりません、よろしくお願いします。

専門家に質問してみよう