`
lobin
  • 瀏覽: 229109 次
  • 性別: Icon_minigender_1
  • 來自: 上海
社區版塊
存檔分類
最新評論

C: Windows編程: 第一章 Windows下C編程

 
閱讀更多
寫道

?

寫道

?

Windows下C編程

?

?

編寫靜態鏈接庫

在C: Linux C 編程中寫過編寫靜態鏈接庫:

寫道
C: Linux C 編程 - 編寫靜態鏈接庫
http://www.xqhtgn.icu/blog/lobin-2326336

通過comment pragma鏈入靜態鏈接庫

?

#pragma comment( comment-type [ , "comment-string" ] )

?

這種方式需要在代碼中通過comment pragma鏈入靜態鏈接庫:

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

?

qt.h

#include <stddef.h>

#if ! defined(QT)
#define QT
struct qt
{
  size_t size;
  char data[];
};

struct qt* qt(int i);

int qt_get(struct qt* v);

int qt_destroy(struct qt* v);
#endif

qt.c

#include<stdlib.h>
#include<string.h>
#include"qt.h"

struct qt* qt(int i)
{
  size_t size = sizeof(i);
  struct qt* v = (struct qt*) malloc(sizeof(struct qt) + size);
  if (v != NULL)
  {
    v->size = size;
    memcpy(v->data, &i, sizeof(i));
  }
  return v;
}

int qt_get(struct qt* v)
{
  int *p = NULL;
  if (v == NULL)
  {
    return 0;
  }
  p = (int *) v->data;
  return *p;
}

int qt_destroy(struct qt* v)
{
  free(v);
  return 0;
}

編譯

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c qt.c

生成靜態庫

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\lib.exe" /nologo qt.obj /out:./qt.lib

?

調用

static_test.c

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

#include <stdio.h>
#include "qt.h"

int main()
{
  int i = 1413;
  struct qt* v = qt(i);
  if (v == NULL)
  {
    return 1;
  }
  printf("qt: i=%d\n", qt_get(v));
  qt_destroy(v);
  return 0;
}

這里調用的時候,通過comment pragma鏈入靜態鏈接庫:

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

?

編譯鏈接

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" static_test.c

?

運行

>.\static_test.exe

qt: i=1413

?

查看程序依賴的庫

這個是查看程序依賴的動態鏈接庫,這里是鏈接的靜態庫,靜態庫代碼直接鏈入到程序中了,所以這里是查看不到依賴的靜態庫的。

?

>ldd static_test.exe

? ? ? ? ntdll.dll => /cygdrive/c/WINDOWS/system32/ntdll.dll (0x7c92000

0)

? ? ? ? kernel32.dll => /cygdrive/c/WINDOWS/system32/kernel32.dll (0x7

c800000)

?

鏈接時直接指定要鏈入的靜態鏈接庫

編譯

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c qt.c

生成靜態庫

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\lib.exe" /nologo qt.obj /out:./qt.lib

?

調用

static_test.c

#include <stdio.h>
#include "qt.h"

int main()
{
  int i = 1413;
  struct qt* v = qt(i);
  if (v == NULL)
  {
    return 1;
  }
  printf("qt: i=%d\n", qt_get(v));
  qt_destroy(v);
  return 0;
}

這里調用的時候,不通過comment pragma鏈入靜態鏈接庫

?

而是在鏈接的時候直接指定要鏈入的靜態鏈接庫

編譯

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c static_test.c

鏈接

>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" static_test.obj ./qt.lib

?

運行

>.\static_test.exe

qt: i=1413

?

查看程序依賴的庫

這個是查看程序依賴的動態鏈接庫,這里是鏈接的靜態庫,靜態庫代碼直接鏈入到程序中了,所以這里是查看不到依賴的靜態庫的。

?

>ldd static_test.exe

? ? ? ? ntdll.dll => /cygdrive/c/WINDOWS/system32/ntdll.dll (0x7c92000

0)

? ? ? ? kernel32.dll => /cygdrive/c/WINDOWS/system32/kernel32.dll (0x7

c800000)

?

?

線程

線程ID

線程ID可以通過GetCurrentThreadId()獲取。

?

線程句柄

創建線程時返回的一個線程句柄。用于指向內部創建的線程對象。

C Run-Time Libraries (CRT)

?

_beginthread和_beginthreadex

?

_beginthread

寫道
uintptr_t _beginthread( // NATIVE CODE
void( __cdecl *start_address )( void * ),
unsigned stack_size,
void *arglist
);
uintptr_t _beginthread( // MANAGED CODE
void( __clrcall *start_address )( void * ),
unsigned stack_size,
void *arglist
);

?

寫道
_CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
unsigned, void *);

_beginthread返回的是新創建線程的句柄。

?

void start_address(void *arg)  
{
  char * name = (char *) arg;
  printf("thread %s\n", name);  
}
   
int main()  
{
  unsigned long th;  
  th = _beginthread(start_address, 0, "1");
  ExitThread(0);  
  return 0;  
}

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthread_test.c

?

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthread_test.exe ./beginthread_test.obj

?

獲取線程返回退出狀態

void start_address(void *args)  
{
  unsigned exit_code = (unsigned) args;
  printf("%d(%u)-%u thread exit(%u)\n", getpid(), GetCurrentProcessId(), GetCurrentThreadId(), exit_code);

  _endthreadex(exit_code);
}
   
int main()  
{
  HANDLE hThread;

  DWORD exit_code = 0;

  hThread = (HANDLE) _beginthread(start_address, 0, (void *) 100);

  WaitForSingleObject(hThread, INFINITE);

  GetExitCodeThread(hThread, &exit_code);
  printf("thread id: %u, exit(%d)\n", -1, exit_code);

  ExitThread(0);
  return 0;  
}

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthread_test2.c

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthread_test2.exe ./beginthread_test2.obj

?

_beginthreadex

?

?

寫道
uintptr_t _beginthreadex( // NATIVE CODE
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
uintptr_t _beginthreadex( // MANAGED CODE
void *security,
unsigned stack_size,
unsigned ( __clrcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);

?

寫道
_CRTIMP unsigned long __cdecl _beginthreadex(void *, unsigned,
unsigned (__stdcall *) (void *), void *, unsigned, unsigned *);

_beginthreadex與_beginthread不同的是,_beginthreadex多了幾個參數:security,initflag以及thrdaddr。

?

initflag

用于指定新創建線程的初始狀態。

如果指定為0,線程創建后將立即執行。

如果指定為CREATE_SUSPENDED,線程創建后不會立即執行,處于掛起狀態。可以調用ResumeThread恢復執行。

如果指定為STACK_SIZE_PARAM_IS_A_RESERVATION,使用stack_size作為初始預留線程棧大小,如果沒有指定為STACK_SIZE_PARAM_IS_A_RESERVATION,stack_size指定的是線程棧的commit大小。

?

thrdaddr
用于返回線程id。

該線程id可以通過GetCurrentThreadId()獲取。

?

_beginthreadex返回的是新創建線程的句柄。

?

unsigned __stdcall start_address(void *arg)  
{  
  char * name = (char *) arg;
  printf("thread %s\n", name);
  return 0;
}  
   
int main()  
{
  unsigned long th;
  unsigned thread;  
  th = _beginthreadex(NULL, 0, start_address, "1", 0, &thread);

  ExitThread(0);
  return 0;  
}

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthreadex_test.c

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthreadex_test.exe ./beginthreadex_test.obj

?

獲取線程返回退出狀態

?

unsigned __stdcall start_address(void *args)  
{  
  unsigned exit_code = (unsigned) args;
  printf("%d(%u)-%u thread exit(%u)\n", getpid(), GetCurrentProcessId(), GetCurrentThreadId(), exit_code);
  return exit_code;
}  
   
int main()  
{
  HANDLE hThread;
  unsigned thread;

  DWORD exit_code = 0;

  hThread = (HANDLE) _beginthreadex(NULL, 0, start_address, (void *) 100, 0, &thread);

  WaitForSingleObject(hThread, INFINITE);

  GetExitCodeThread(hThread, &exit_code);
  printf("thread id: %u, exit(%d)\n", thread, exit_code);

  ExitThread(0);
  return 0;  
}

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthreadex_test3.c

?

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthreadex_test3.exe ./beginthreadex_test3.obj

?

C Run-Time Library _beginthread, _beginthreadex to create thread

#ifndef _MT
#error "Compiler linking options /MT not specific"
#endif
 
#include <stdio.h>
#include <windows.h>
#include <process.h>
 
void start_address(void *arg)
{
printf("_beginthread start_address\n");
}
 
unsigned __stdcall start_address_ex(void *arg)
{
printf("_beginthreadex start_address_ex\n");
return 0;
}
 
int main()
{
#ifdef _MT 
printf("MT defined\n");
#endif
 
unsigned long th;
printf("Thread _beginthread test\n");
th = _beginthread(start_address, 
0, 
NULL);
printf("_beginthread return %ld\n", th);
 
unsigned thread;
// CREATE_SUSPENDED 
th = _beginthreadex(NULL, 0, start_address_ex, NULL, 0, &thread);
ExitThread(0);
return 0;
}
 
====================================
 
DEBUG=../Debug
PATH_VS=D:\usr\bin\Microsoft Visual Studio\VC98
CL="$(PATH_VS)\Bin\cl.exe"
LINK="$(PATH_VS)\Bin\link.exe"
 
INCLUDE="D:\usr\bin\Microsoft Visual Studio\VC98\Include"
LIB="D:\usr\bin\Microsoft Visual Studio\VC98\Lib"
INCLUDE_LIB_LOG=D:\home\admin\workstation\c\liblog
LIB_LIB_LOG=D:\home\admin\workstation\c\liblog\Debug
 
 
 
liblog.lib: clean 
 
# using compiler linking options /MT, If compiles _beginthread edition of Thread
$(CL) /GX /W3 /MT /I $(INCLUDE) /c /Fo$(DEBUG)/ ThreadTest__beginthread.cpp
 
$(LINK) /LIBPATH:$(LIB) /OUT:$(DEBUG)/Thread_beginthreadTest.exe $(DEBUG)/*.obj
 
clean:
rm -Rf ./*.bak
rm -Rf ./*.o
rm -Rf ./*.obj
rm -Rf ./*.exe
rm -Rf ../Debug/*
 
===========================================
 
運行結果:
 
MT defined
Thread _beginthread test
_beginthread return 2024
_beginthread start_address
_beginthreadex start_address_ex
 

?

?

0
1
分享到:
評論
Global site tag (gtag.js) - Google Analytics 开心农场种蔬菜赚钱 ipad能看股票行情吗 广东11选5官网 新疆11选5杀号 幸运飞艇骗局视频 河北快3快3跨度表 浙江11选五遗漏 贵州高频十一选五走势 北京pk10全天计划软件 中国体育彩票app下载安装 广西十一选五开奖结果走势图 百度 11选5内蒙古遗漏号查 江西时时彩号码直播 湖南快乐十分开奖结果1000期 天津11选5任选基本走势 网上五分快三骗局揭秘 广西快乐十分即时开奖