2025年2月2日日曜日

Go言語入門(6)

 

興味本位でGo言語に触れてみようと思う。WSLで64bit Windows DLLを生成してしてみる。で、DllMainが必要な時にどうするかってところまで。



参考サイトはこちら(https://qiita.com/h6591/items/18620f0ac93ea1ae219b)。で、もうメンドクサイので作ったファイルを載せていく。

dlltry1.go
  1. package main
  2.  
  3. import "C"
  4.  
  5. //export tasu
  6. func tasu(a int,b int) int {
  7.     return a+b
  8. }
  9.  
  10. func main(){
  11. }
エクスポートする関数の上にコメントっぽくexportって書かんといかんのだけど、こんないい加減な書き方でいいの?ってドキドキしちゃう。

Makefile
  1. OPT_CC= CC=x86_64-w64-mingw32-gcc
  2. #OPT_CC= CC=i686-w64-mingw32-gcc
  3. OPT_CGO= CGO_ENABLED=1
  4. OPT_OS= GOOS=windows
  5. OPT_ARCH= GOARCH=amd64
  6. #OPT_ARCH= GOARCH=386
  7. GOFLAGS=build -buildmode=c-shared
  8. #GOFLAGS=build -ldflags "-s -w" -buildmode=c-shared
  9. GO=go
  10. SRCS=dlltry1.go
  11. TARGET=dlltry1.dll
  12.  
  13. $(TARGET) : $(SRCS)
  14.     $(OPT_CC) $(OPT_CGO) $(OPT_OS) $(OPT_ARCH) $(GO) $(GOFLAGS) -o $(TARGET) $(SRCS)
  15.  
  16. clean :
  17.     rm dlltry1.dll dlltry1.h
まぁMakefileとか要らんレベルなんやけど、書くことがめっちゃ多いから、何度もやるってなった時のために。

dlltest1.c
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <windows.h>
  4. typedef int (__stdcall *tasu_type)(int a,int b);
  5. HMODULE dll;
  6. tasu_type tasu;
  7.  
  8. int main(int argc,char** argv){
  9.     int r;
  10.     dll=LoadLibrary("dlltry1.dll");
  11.     tasu=(tasu_type)GetProcAddress(dll,"tasu");
  12.     r=tasu(55,41);
  13.     printf("%d\n",r);
  14.     return 0;
  15. }
テストアプリはCで書く。まぁ、あえてCから呼び出すのもいいでしょ。
で、ビルドしてテストアプリをコンパイルして実行してみる。
make
x86_64-w64-mingw32-gcc dlltest1.c
ls -la
./a.exe
はい。うまくいきました。よかった。
それで今度は、DllMainでDLL_PROCESS_ATTACHとかのイベントで動作させたいときにどうするかってのだけど、cgo使うわけでいっそのことCで書いちゃえば良いってわけだ。で、やってみる。

dlltry2.go
  1. package main
  2.  
  3. import "C"
  4.  
  5. //export tasu
  6. func tasu(a int,b int) int {
  7.     return a+b
  8. }
  9.  
  10. func main(){
  11. }

dllmain.go
  1. package main
  2.  
  3. /*#include "dllmain.h"*/
  4. import "C"

dllmain.h
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <windows.h>
  4.  
  5. STARTUPINFO si;
  6. PROCESS_INFORMATION pi;
  7.  
  8. int32_t initialize(){
  9.     ZeroMemory(&si,sizeof(si));
  10.     si.cb=sizeof(si);
  11.     ZeroMemory(&pi,sizeof(pi));
  12.     if(!CreateProcess(NULL,"calc.exe",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)){
  13.         printf( "(C)CreateProcess failed (%d).\n", GetLastError() );
  14.         return -1;
  15.     }
  16.     return 0;
  17. }
  18. void finalize(){
  19.     // Close process and thread handles.
  20.     CloseHandle( pi.hProcess );
  21.     CloseHandle( pi.hThread );
  22. }
  23.  
  24. BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved ){
  25.     switch( fdwReason )
  26.     {
  27.         case DLL_PROCESS_ATTACH:
  28.             printf("DLL_PROCESS_ATTACH\n");
  29.             initialize();
  30.             break;
  31.  
  32.         case DLL_THREAD_ATTACH:
  33.             printf("DLL_THREAD_ATTACH\n");
  34.             break;
  35.  
  36.         case DLL_THREAD_DETACH:
  37.             printf("DLL_THREAD_DETACH\n");
  38.             break;
  39.  
  40.         case DLL_PROCESS_DETACH:
  41.             printf("DLL_PROCESS_DETACH_1\n");
  42.             if (lpvReserved != NULL){
  43.                 break; // do not do cleanup if process termination scenario
  44.             }
  45.             printf("DLL_PROCESS_DETACH_2\n");
  46.             finalize();
  47.             break;
  48.     }
  49.     return TRUE;
  50. }

Makefile
  1. OPT_CC= CC=x86_64-w64-mingw32-gcc
  2. #OPT_CC= CC=i686-w64-mingw32-gcc
  3. OPT_CGO= CGO_ENABLED=1
  4. OPT_OS= GOOS=windows
  5. OPT_ARCH= GOARCH=amd64
  6. #OPT_ARCH= GOARCH=386
  7. GOFLAGS=build -buildmode=c-shared
  8. #GOFLAGS=build -ldflags "-s -w" -buildmode=c-shared
  9. GO=go
  10. #SRCS=dll64wdllmain.go dllmain.go
  11. SRCS=dlltry2.go dllmain.go
  12. TARGET=dlltry2.dll
  13.  
  14. $(TARGET) : $(SRCS)
  15.     $(OPT_CC) $(OPT_CGO) $(OPT_OS) $(OPT_ARCH) $(GO) $(GOFLAGS) -o $(TARGET) $(SRCS)
  16. clean :
  17.     rm dlltry2.dll dlltry2.h
  18.  

dlltest2.c
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <windows.h>
  4. typedef int (__stdcall *tasu_type)(int a,int b);
  5. HMODULE dll;
  6. tasu_type tasu;
  7.  
  8. int main(int argc,char** argv){
  9.     int r;
  10.     dll=LoadLibrary("dlltry2.dll");
  11.     tasu=(tasu_type)GetProcAddress(dll,"tasu");
  12.     r=tasu(55,41);
  13.     printf("%d\n",r);
  14.     return 0;
  15. }
これで、DLLロード時に電卓が起動されて、各イベントごとに標準出力にprintfで出力されるはず。で、ビルドしてテストアプリをコンパイルして実行してみる。
make
x86_64-w64-mingw32-gcc dlltest2.c
ls -la
./a.exe
そすっと、
電卓は立ち上がるわコンソールにいろいろ出力されるわで、、、期待通り、、、です(∩´∀`)∩ワーイ、、、(DLL_PROCESS_DETACH_2が出力されていないのがなんでなのか、、、ま、いいか)
 
、、、突然始まったこの活動、実はある目的に向かっているんだけど、こんどの土曜日には何だったのか忘れているかもしれない。なら、ここに書いておけば?ってのも思うけど、まだやれてもいないのに書いちゃって検索で引っかかると申し訳ないじゃんね。だから書けない。検索して、見つけたーって開いたら「、、、をやるつもり」的な記述だと殺意に近い憎悪をおぼえるよね(´∀`)

0 件のコメント:

コメントを投稿