`
lobin
  • 浏览: 425294 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多
写道

 

写道

 

 

写道

 

写道

 

Windows下C编程主要就是微软的VC环境。

 

Visual C++下的C/C++编程主要包括Win32控制台程序、Win32应用程序以及MFC应用程序,当然还可以编写Win32和MFC程序库。Win32控制台程序和Win32应用程序的区别在于链接时指定的/subsystem选项不同,Win32控制台程序链接时/subsystem选项指定的是/subsystem:console,而Win32应用程序链接时/subsystem选项指定的是/subsystem:windows。至于MFC应用程序,严格来说,这并不是一种应用程序类型,MFC全称为“Microsoft Foundation Class (MFC) Library”,这个其实只是一个库,或者说是一个编程框架。不管是开发Win32控制台程序还是Win32应用程序,都可以像引入一个第三方库一样引入MFC。这里主要是Visual C++下开发控制台程序。

 

 

C/C++程序的入口函数是main函数,这是C/C++程序的标准main入口函数。

 

main

 

Visual C++还提供了几个入口函数。比如wmain、_tmain,以及编写Win32和MFC应用程序的WinMain、wWinMain和_tWinMain。

 

wmain

这里的wmain和我们平常的main不同的就是前面带了一个w,这个w不是指的window或者窗口的意思,而是指的是wide宽字符的意思。wmain函数是main函数的宽字符版本。

 

关于main和wmain可参考这篇文章:

 

写道

 

https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-6.0/aa299386(v=vs.60)?redirectedfrom=MSDN

 

 

_tmain

这个其实就是一个宏定义,它最后还是会被替换为main或者wmain。使用_tmain做入口函数的时候要引入tchar.h头文件。

#include <tchar.h>

int _tmain()
{
  printf("this is _tmain.\n");
  return 0;
}

_tmain其实就只是一个在tchar.h中定义的宏,在宽字符环境下,_tmain被替换为wmain,否则还是会被替换为main,和我们平常写的main一样。

 

#ifdef  _UNICODE
...
#define _tmain      wmain
...
#else   /* ndef _UNICODE */
...
#define _tmain      main
...
#endif

在上面的例子中,如果在窄字符环境下,替换之后就是我们熟悉的int main() {...}。

#include <tchar.h>

int _tmain(int argc, TCHAR* argv[])
{
  printf("this is _tmain.\n");
  return 0;
}

在这个例子中,如果在窄字符环境下,替换之后就是我们熟悉的int main(int argc, char *argv[]) {...}。

 

#include <tchar.h>

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
  printf("this is _tmain.\n");
  return 0;
}

在这个例子中,如果在窄字符环境下,替换之后就是我们熟悉的int main(int argc, char *argv[], char *envp[]) {...}。

 

WinMain

 

INT WinMain(HINSTANCE hInstance, 
    HINSTANCE hPrevInstance,
    PSTR lpCmdLine, 
    INT nCmdShow);

 

wWinMain

int WINAPI wWinMain(HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    PWSTR pCmdLine, 
    int nCmdShow);

 

 

_tWinMain

 

 

#ifdef  _UNICODE
...
#define _tWinMain   wWinMain
...
#else   /* ndef _UNICODE */
...
#define _tWinMain   WinMain
...
#endif

 

编写静态链接库

在C: Linux C 编程中写过编写静态链接库:

写道
C: Linux C 编程 - 编写静态链接库
https://www.iteye.com/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
 

 

自定义控制台窗口图标

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#include "resource.h"

typedef HWND (WINAPI * GETCONSOLEPROC)();

HWND GetConsole()
{
  HWND hRet(NULL);
  BOOL bLoad(FALSE);

  HMODULE hMod = GetModuleHandle(_T("kernel32.dll"));
  if(hMod == NULL)
  {
    hMod = LoadLibrary(_T("kernel32.dll"));    
    bLoad = TRUE;
  }
  if(hMod != NULL)
  {
	GETCONSOLEPROC pFun = (GETCONSOLEPROC) GetProcAddress(hMod, "GetConsoleWindow");
    if(pFun != NULL)
    {
      hRet = pFun();
    }
    if(bLoad)
    {
      FreeLibrary(hMod);
    }
  }
  return hRet;
}

int main(int argc, char* argv[])
{
  HWND hConsole = GetConsole();
  if(hConsole != NULL)
  {
    HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
    SendMessage(hConsole, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
    SendMessage(hConsole, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
  }
  printf("hello c!\n");
  return 0;
}

resource.h

#define IDI_ICON1                       101

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

rs.rc

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Chinese (中国) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1               ICON    DISCARDABLE     "icon.ico"
#endif    // Chinese (中国) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

编译源程序

>cl /c console_test.cpp

编译资源

>"D:\usr\bin\Microsoft Visual Studio\Common\MSDev98\Bin\RC.EXE" /fo"rs.res" rs.rc

 

链接

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./console_test.exe ./console_test.obj rs.res user32.lib

 

 

 

中断

 

中断处理函数

 

C编写中断处理函数不是那么容易的。中断处理函数和普通的函数不一样,中断处理函数不像普通函数那样使用ret返回,它使用iret返回退出中断。此外,中断处理函数要求是可重入函数。现在很多编译器(包括C编译器)都不支持编写中断处理函数。C语言标准也没有对中断处理函数标准化。

 

一些C编译器通过扩展来提供中断处理函数,如TURBO C,GCC等。

 

TURBO C编写中断处理函数可参考下面的例子。

 

线程 

 

C++:线程封装

/*
 * Thread that support cross platform and support global and local start routine, and support 
 * Windows api and C Run-Time Library(even extension) on windows. 
 * <p>
 * To implements a simple thread, only to overrides the run method.
 *
 * @author ada
 * @version 1.0
 * @since 1.0
 */
#include <windows.h>
#include "Runnable.hpp"
 
#if ! defined THREAD
#define THREAD
 
// GLOBAL_START_ROUTINE is a user defined macro, likes a switch, to determine whether to 
// select global thread start routine or not. GLOBAL_START_ROUTINE can be defined in program, 
// or using compiler preprocessor options(PREPROCESSOR) /D to define user defined macro 
// GLOBAL_START_ROUTINE to compiles global start routine edition of Thread
#if defined GLOBAL_START_ROUTINE 
 
#define _GLOBAL_START_ROUTINE
#pragma message ("GLOBAL_START_ROUTINE defined, using global thread start routine.")
 
// using compiler linking options /MT to compiles C Run-Time Library(_beginthread, _beginthreadex) 
// edition of Thread
#if defined(_MT) && (! defined(_MT_RT_EX))
#pragma message ("Using C Run-Time Library global thread start routine.")
//#error "C Run-Time Library global thread start routine not supported."
void execute(void *args);
 
#elif defined(_MT) && defined(_MT_RT_EX)
#pragma message ("Using C Run-Time Library extension global thread start routine.")
//#error "C Run-Time Library extension global thread start routine not supported."
unsigned __stdcall execute(void *arg);
 
#else 
DWORD execute(LPVOID args);
#endif
 
#else 
 
#pragma message ("GLOBAL_START_ROUTINE not defined, do not using global thread start routine.")
// If GLOBAL_START_ROUTINE not defined, for thread start routine function details, See Thread class 
// declaration when user defined macro defined
#endif
 
/**
 *
 *
 *
 */
class /*TK_API*/ Thread : public Runnable 
{
 
private:
 
DWORD threadID;
 
Runnable *target;
 
public:
 
Thread();
 
Thread(const Runnable *runnable);
 
#if ! defined _GLOBAL_START_ROUTINE
#if defined(_MT) && (! defined(_MT_RT_EX))
#pragma message ("Using C Run-Time Library global thread start routine.")
#error "C Run-Time Library global thread start routine not supported."
#elif defined(_MT) && defined(_MT_RT_EX)
#pragma message ("Using C Run-Time Library extension global thread start routine.")
#error "C Run-Time Library extension global thread start routine not supported."
#else 
static DWORD execute(LPVOID args);
#endif
#endif
 
void start();
 
virtual void run();
 
};
 
#endif
 
======================================================================
 
/*
 *
 *
 * @AUTHOR ADA
 * @VERSION 1.0
 * @SINCE 1.0
 */
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <windows.h>
#include <log.h>
#include "Thread.hpp"
 
//#define _MT
using namespace std;
 
#if ! defined _GLOBAL_START_ROUTINE 
DWORD Thread::execute(LPVOID args)
{
Thread* t = (Thread *) args;
    t->run();
return 1;
}
#else 
#if defined(_MT) && (! defined(_MT_RT_EX))
void execute(void *args)
{
Thread* t = (Thread *) args;
    t->run();
}
#elif defined(_MT) && defined(_MT_RT_EX)
unsigned __stdcall execute(void *arg)
{
Thread* t = (Thread *) args;
    t->run();
return 0;
}
#else
DWORD execute(LPVOID args) 
{
Thread* t = (Thread *) args;
    t->run();
return 1;
}
#endif
#endif
 
/**
 *
 *
 *
 */
Thread::Thread() 
{
    this->threadID = 0;
this->target = NULL;
}
 
Thread::Thread(const Runnable *runnable)
{
this->threadID = 0;
this->target = (Runnable *) runnable;
}
 
void Thread::start() 
{
#ifndef _GLOBAL_START_ROUTINE
LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
::CreateThread(NULL, 0, startRoutine, (LPVOID) this, 0, &(this->threadID));
 
debug("Thread %d started", this->threadID);
}
 
void Thread::run() 
{
if (target != NULL) 
{
   target->run();
}
else 
{
debug("Thread::run()");
}
}
 
 
================================================================================
 
#ifndef _MT
#error "Compiler linking options /MT not specific"
#endif
 
#include <stdio.h>
#include <windows.h>
#include <process.h>
 
#include "../Thread.hpp"
#include "../LinkedLibrary.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()
{
printf("Thread test\n");
 
#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);
 
 
Thread *t = new Thread();
t->start();
 
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
 
INCLUDE_MYSQL=D:\usr\srv\mysql51\include
LIB_MYSQL=D:\usr\srv\mysql51\lib\debug
 
INCLUDE_LUA=D:\usr\bin\Lua\5.1\include
LIB_LUA=D:\usr\bin\Lua\5.1\lib
 
liblog.lib: clean 
 
# using compiler linking options /MT, If compiles _beginthread edition of Thread
$(CL) /GX /W3 /MT /DGLOBAL_START_ROUTINE /I $(INCLUDE) /I $(INCLUDE_LIB_LOG) /c /Fo$(DEBUG)/ ../Thread.cpp
$(CL) /GX /W3 /MT /DGLOBAL_START_ROUTINE /I $(INCLUDE) /c /Fo$(DEBUG)/ ThreadTest__beginthread.cpp
 
$(LINK) /LIBPATH:$(LIB) /LIBPATH:$(LIB_LIB_LOG) /LIBPATH:$(LIB_MYSQL) /LIBPATH:$(LIB_LUA) /OUT:$(DEBUG)/ThreadTest__beginthread.exe $(DEBUG)/*.obj
cp ../liblog.dll $(DEBUG)
clean:
rm -Rf ./*.bak
rm -Rf ./*.o
rm -Rf ./*.obj
rm -Rf ./*.exe
rm -Rf ../Debug/*
 
 

 

 

C++ Thread class

/*
 * Thread that support cross platform and support global and local start routine, and support 
 * Windows api and C Run-Time Library(even extension) on windows. 
 * <p>
 * To implements a simple thread, only to overrides the run method.
 *
 * @author ada
 * @version 1.0
 * @since 1.0
 */
#include <windows.h>
#if defined(_WIN32) && defined(_MT)
#include <process.h>
#endif
#include "Runnable.hpp"
 
#if ! defined THREAD
#define THREAD
 
// GLOBAL_START_ROUTINE is a user defined macro, likes a switch, to determine whether to 
// select global thread start routine or not. GLOBAL_START_ROUTINE can be defined in program, 
// or using compiler preprocessor options(PREPROCESSOR) /D to define user defined macro 
// GLOBAL_START_ROUTINE to compiles global start routine edition of Thread
#if defined GLOBAL_START_ROUTINE 
 
#define _GLOBAL_START_ROUTINE
#pragma message ("GLOBAL_START_ROUTINE defined, using global thread start routine.")
 
// windows
#ifdef _WIN32 
// using compiler linking options /MT to compiles C Run-Time Library(_beginthread, _beginthreadex) 
// edition of Thread
#if defined(_MT) && (! defined(_MT_RT_EX))
#pragma message ("Using C Run-Time Library global thread start routine.")
//#error "C Run-Time Library global thread start routine not supported."
void execute(void *args);
typedef void (* LP_CRT_THREAD_START_ROUTINE)(void *args);
 
#elif defined(_MT) && defined(_MT_RT_EX)
#pragma message ("Using C Run-Time Library extension global thread start routine.")
//#error "C Run-Time Library extension global thread start routine not supported."
unsigned __stdcall execute(void *args);
typedef unsigned (__stdcall * LP_CRT_EX_THREAD_START_ROUTINE)(void *args);
 
#else 
DWORD execute(LPVOID args);
#endif
 
// linux
#else
void* execute(void *args);
#endif
 
// User defined macro GLOBAL_START_ROUTINE is not specific
// Compiles global start routine edition of Thread using compiler preprocessor options(PREPROCESSOR) /D 
// to define user defined macro GLOBAL_START_ROUTINE
#else 
 
#pragma message ("GLOBAL_START_ROUTINE not defined, do not using global thread start routine.")
// If GLOBAL_START_ROUTINE not defined, for thread start routine function details, See Thread class 
// declaration when user defined macro defined
#endif
 
/**
 *
 *
 *
 */
class /*TK_API*/ Thread : public Runnable 
{
 
private:
 
#if defined(_WIN32) && defined(_MT)
#ifdef _MT_RT_EX
unsigned threadID;
#else
unsigned long threadID;
#endif
#else
DWORD threadID;
#endif
 
Runnable *target;
 
public:
 
Thread();
 
Thread(const Runnable *runnable);
 
#if ! defined _GLOBAL_START_ROUTINE
// windows
#ifdef _WIN32 
#if defined(_MT) && (! defined(_MT_RT_EX))
#pragma message ("Using C Run-Time Library global thread start routine.")
#error "C Run-Time Library global thread start routine not supported."
#elif defined(_MT) && defined(_MT_RT_EX)
#pragma message ("Using C Run-Time Library extension global thread start routine.")
#error "C Run-Time Library extension global thread start routine not supported."
#else 
static DWORD execute(LPVOID args);
#endif
// linux
#else
static void* execute(void *args);
#endif
#endif
 
void start();
 
virtual void run();
 
};
 
#endif
 
======================================================================
 
/*
 *
 *
 * @AUTHOR ADA
 * @VERSION 1.0
 * @SINCE 1.0
 */
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <windows.h>
#include <log.h>
#include "Thread.hpp"
 
//#define _MT
using namespace std;
 
#if ! defined _GLOBAL_START_ROUTINE 
DWORD Thread::execute(LPVOID args)
{
Thread* t = (Thread *) args;
    t->run();
return 1;
}
#else 
#if defined(_MT) && (! defined(_MT_RT_EX))
void execute(void *args)
{
debug("start routine defined(_MT) && (! defined(_MT_RT_EX))");
Thread* t = (Thread *) args;
    t->run();
}
#elif defined(_MT) && defined(_MT_RT_EX)
unsigned __stdcall execute(void *args)
{
debug("start routine defined(_MT) && defined(_MT_RT_EX)");
Thread* t = (Thread *) args;
    t->run();
return 0;
}
#else
DWORD execute(LPVOID args) 
{
Thread* t = (Thread *) args;
    t->run();
return 1;
}
#endif
#endif
 
/**
 *
 *
 *
 */
Thread::Thread() 
{
    this->threadID = 0;
this->target = NULL;
}
 
Thread::Thread(const Runnable *runnable)
{
this->threadID = 0;
this->target = (Runnable *) runnable;
}
 
void Thread::start() 
{
#if defined(_MT) && (! defined(_MT_RT_EX))
#ifndef _GLOBAL_START_ROUTINE
LP_CRT_THREAD_START_ROUTINE startRoutine = (LP_CRT_THREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LP_CRT_THREAD_START_ROUTINE startRoutine = (LP_CRT_THREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
 
#elif defined(_MT) && defined(_MT_RT_EX)
#ifndef _GLOBAL_START_ROUTINE
LP_CRT_EX_THREAD_START_ROUTINE startRoutine = (LP_CRT_EX_THREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LP_CRT_EX_THREAD_START_ROUTINE startRoutine = (LP_CRT_EX_THREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
 
#else
#ifndef _GLOBAL_START_ROUTINE
LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
#endif
 
#if defined(_MT) && (! defined(_MT_RT_EX))
debug("begin thread through _beginthread()");
threadID = _beginthread(startRoutine, 
0, 
(void *) this);
#elif defined(_MT) && defined(_MT_RT_EX)
debug("begin thread through _beginthreadex()");
threadID =  _beginthreadex(NULL, 0, startRoutine, (void *) this, 0, &(this->threadID));
#else
::CreateThread(NULL, 0, startRoutine, (LPVOID) this, 0, &(this->threadID));
#endif
 
debug("Thread %d started", this->threadID);
}
 
void Thread::run() 
{
if (target != NULL) 
{
   target->run();
}
else 
{
debug("Thread::run()");
}
 
}
 

 

 

 

 

 

Windows下C/C++ 多线程同步(mutex)

#ifndef __LOCK
#define __LOCK
 
class Lock
{
public:
 
virtual void lock() = 0;
 
virtual void unlock() = 0;
};
 
#endif
 
=======================================
 
#include <windows.h>
#include "Lock.hpp"
 
#ifndef _MUTEX_LOCK
#define _MUTEX_LOCK
 
class MutexLock : public Lock
{
 
private: 
 
HANDLE mutex;
 
public:
MutexLock();
 
MutexLock(const char* name);
 
void lock();
 
void lock(HANDLE mutex);
 
void unlock();
 
void unlock(HANDLE mutex);
 
HANDLE getMutex();
};
 
#endif
 
========================================
 
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "log.h"
#include "MutexLock.hpp"
 
MutexLock::MutexLock()
{
this->mutex = CreateMutex(NULL, FALSE, NULL);
if (this->mutex == NULL) 
{
DWORD error = GetLastError();
warn("create mutex error %d", error);
}
debug("MutexLock()");
}
 
MutexLock::MutexLock(const char* name) 
{
this->mutex = CreateMutex(NULL, FALSE, name);
if (this->mutex == NULL) 
{
DWORD error = GetLastError();
warn("create mutex error %d", error);
}
else 
{
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS) 
{
debug("mutex name %s already exists, use the existed mutex instead.", name);
}
}
}
 
void MutexLock::lock()
{
lock(this->mutex);
}
 
void MutexLock::lock(HANDLE mutex)
{
DWORD event = WaitForSingleObject(mutex, INFINITE);
if (event == WAIT_FAILED) 
{
DWORD error = GetLastError();
warn("wait error %d", error);
}
else if(event == WAIT_TIMEOUT) 
{
debug("wait time out");
}
else if(event == WAIT_ABANDONED) 
{
debug("wait abandoned");
}
}
 
void MutexLock::unlock()
{
this->unlock(this->mutex);
}
 
void MutexLock::unlock(HANDLE mutex) 
{
BOOL isr = ReleaseMutex(this->mutex);
if (! isr) 
{
DWORD error = GetLastError();
warn("release mutex error %d", error);
}
}
 
HANDLE MutexLock::getMutex()
{
return this->mutex;
}
 
========================================
 
#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <windows.h>
#include "../MutexLock.hpp"
#include "../Thread.hpp"
 
 
#ifndef MESSAGE_DESTINATION
#define MESSAGE_DESTINATION
 
class MessageDestination 
{
private: 
MutexLock lock;
 
int i;
 
public:
MessageDestination()
{
i = 0;
}
 
void add()
{
lock.lock();
i++;
printf("[Producer] message %d\n", this->i);
lock.unlock();
 
}
 
void reduce()
{
lock.lock();
i--;
printf("[Consumer] message %d\n", i);
lock.unlock();
}
};
#endif
 
===========================================
 
#include <stdio.h>
#include "../MutexLock.hpp"
#include "../Thread.hpp"
#include "MessageDestination.hpp"
 
class MessageConsumer : public Thread 
{
private:
MessageDestination *destination;
 
 
public: 
MessageConsumer()
{
this->destination = NULL;
}
 
void registerConsumer(MessageDestination *destination) 
{
this->destination = destination;
}
 
 
void run() 
{
while (1)
{
if (destination != NULL) 
{
this->destination->reduce();
}
//Sleep(500);
}
}
};
 
=========================================
 
#include <stdio.h>
#include "../MutexLock.hpp"
#include "../Thread.hpp"
#include "MessageDestination.hpp"
 
class MessageProducer : public Thread 
{
private:
MessageDestination *destination;
 
public: 
MessageProducer()
{
this->destination = NULL;
}
 
void registerProducer(MessageDestination *destination) 
{
this->destination = destination;
}
 
void run()
{
while (1) 
{
if (destination != NULL) 
{
destination->add();
}
//Sleep(5000);
}
}
};
 
==========================================
 
#include "MessageDestination.hpp"
#include "MessageProducer.hpp"
#include "MessageConsumer.hpp"
 
void main()
{
///*
MessageDestination *destination = new MessageDestination();
 
MessageProducer *producer = new MessageProducer();
producer->registerProducer(destination);
producer->start();
 
MessageConsumer *consumer = new MessageConsumer();
consumer->registerConsumer(destination);
consumer->start();
 
 
ExitThread(0);
 
}
 

 

 

Windows下C/C++ 多线程同步(event)

#ifndef __LOCK
#define __LOCK
 
class Lock
{
public:
 
virtual void lock() = 0;
 
virtual void unlock() = 0;
};
 
#endif
 
===========================================================
 
#include <windows.h>
#include "Lock.hpp"
 
#ifndef _EVENT_LOCK
#define _EVENT_LOCK
 
class EventLock : public Lock
{
 
private: 
 
HANDLE event;
 
public:
EventLock();
 
EventLock(const char* name);
 
virtual void lock();
 
void lock(HANDLE event);
 
virtual void unlock();
 
void unlock(HANDLE event);
 
HANDLE getEvent();
};
 
#endif
 
 
============================================================
 
 
 
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "log.h"
#include "EventLock.hpp"
 
EventLock::EventLock()
{
this->event = CreateEvent(NULL, FALSE, TRUE, NULL);
if (this->event == NULL) 
{
DWORD error = GetLastError();
warn("create event error %d", error);
}
debug("EventLock()");
}
 
EventLock::EventLock(const char* name) 
{
this->event = CreateEvent(NULL, FALSE, FALSE, name);
if (this->event == NULL) 
{
DWORD error = GetLastError();
warn("create event error %d", error);
}
else 
{
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS) 
{
debug("event name %s already exists, use the existed event instead.", name);
}
}
}
 
void EventLock::lock()
{
lock(this->event);
}
 
void EventLock::lock(HANDLE event)
{
DWORD e = WaitForSingleObject(event, INFINITE);
if (e == WAIT_FAILED) 
{
DWORD error = GetLastError();
warn("wait error %d", error);
}
else if(e == WAIT_TIMEOUT) 
{
debug("wait time out");
}
else if(e == WAIT_ABANDONED) 
{
debug("wait abandoned");
}
}
 
void EventLock::unlock()
{
this->unlock(this->event);
}
 
void EventLock::unlock(HANDLE event) 
{
BOOL isr = SetEvent(this->event);
if (! isr) 
{
DWORD error = GetLastError();
warn("release event error %d", error);
}
}
 
HANDLE EventLock::getEvent()
{
return this->event;
}
 
 
 
================================================================
 
#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <windows.h>
#include "../Lock.hpp"
#include "../EventLock.hpp"
#include "../Thread.hpp"
 
 
#ifndef TEST_EVENT_LOCK_MESSAGE_DESTINATION
#define TEST_EVENT_LOCK_MESSAGE_DESTINATION
 
class TestEventLockMessageDestination 
{
private: 
Lock *lock;
//HANDLE hEvent;
int i;
 
public:
TestEventLockMessageDestination()
{
lock = new EventLock();
//hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
i = 0;
}
 
void add()
{
lock->lock();
i++;
printf("[Producer] message %d\n", this->i);
/*
if (i > 0) 
{
SetEvent(hEvent);
}
*/
lock->unlock();
 
}
 
void reduce()
{
lock->lock();
/*
if (i <= 0) 
{
ResetEvent(hEvent);
WaitForSingleObject(hEvent, INFINITE);
}
*/
 
i--;
printf("[Consumer] message %d\n", i);
 
lock->unlock();
}
};
#endif
 
==============================================================
 
#include <stdio.h>
#include "../Thread.hpp"
#include "TestEventLockMessageDestination.hpp"
 
#ifndef TEST_EVENT_LOCK_MESSAGE_PRODUCER
#define TEST_EVENT_LOCK_MESSAGE_PRODUCER
 
class TestEventLockMessageProducer : public Thread 
{
private:
TestEventLockMessageDestination *destination;
 
public: 
TestEventLockMessageProducer()
{
this->destination = NULL;
}
 
void registerProducer(TestEventLockMessageDestination *destination) 
{
this->destination = destination;
}
 
void run()
{
while (1) 
{
if (destination != NULL) 
{
destination->add();
}
Sleep(5000);
}
}
};
#endif
 
 
======================================
 
 
#include <stdio.h>
#include "../Thread.hpp"
#include "TestEventLockMessageDestination.hpp"
 
#ifndef TEST_EVENT_LOCK_MESSAGE_CONSUMER
#define TEST_EVENT_LOCK_MESSAGE_CONSUMER
 
class TestEventLockMessageConsumer : public Thread 
{
private:
TestEventLockMessageDestination *destination;
 
 
public: 
TestEventLockMessageConsumer()
{
this->destination = NULL;
}
 
void registerConsumer(TestEventLockMessageDestination *destination) 
{
this->destination = destination;
}
 
 
void run() 
{
while (1)
{
if (destination != NULL) 
{
this->destination->reduce();
}
Sleep(500);
}
}
};
#endif
 
 
==================================
 
 
#include "TestEventLockMessageDestination.hpp"
#include "TestEventLockMessageProducer.hpp"
#include "TestEventLockMessageConsumer.hpp"
 
void main()
{
///*
TestEventLockMessageDestination *destination = new TestEventLockMessageDestination();
 
TestEventLockMessageProducer *producer = new TestEventLockMessageProducer();
producer->registerProducer(destination);
producer->start();
 
TestEventLockMessageConsumer *consumer = new TestEventLockMessageConsumer();
consumer->registerConsumer(destination);
consumer->start();
 
/*
while(1)
{
Sleep(2000);
}
*/
ExitThread(0);
 
 
/*
DWORD threadID;
CreateThread(NULL, 0, Callback1, (LPVOID) NULL, 0, &threadID);
printf("Thread %ld started...\n", threadID);
 
CreateThread(NULL, 0, Callback2, (LPVOID) NULL, 0, &threadID);
printf("Thread %ld started...\n", threadID);
 
ExitThread(0);
*/
}
 

Windows下C/C++ 多线程同步

 

#include "Lock.hpp"
#include "EventLock.hpp"
 
#ifndef __SYNC
#define __SYNC
class Sync 
{
private:
 
protected:
 
EventLock *lock;
 
EventLock *block;
 
public:
 
Sync();
 
void wait();
 
void notify();
 
};
#endif
 
==========================================
 
#include "EventLock.hpp"
#include "Sync.hpp"
 
Sync::Sync()
{
lock = new EventLock();
block = new EventLock();
}
 
void Sync::wait()
{
block->setState(EventLock::NON_SIGNALED);
lock->unlock();
block->lock();
lock->lock();
}
 
void Sync::notify()
{
block->setState(EventLock::SIGNALED);
}
 
===========================================
 
#include <windows.h>
#include "Lock.hpp"
 
#ifndef _EVENT_LOCK
#define _EVENT_LOCK
 
class EventLock : public Lock
{
 
private: 
 
HANDLE event;
 
public:
const static int SIGNALED;
 
const static int NON_SIGNALED;
 
EventLock();
 
EventLock(const char* name);
 
virtual void lock();
 
void lock(HANDLE event);
 
virtual void unlock();
 
void unlock(HANDLE event);
 
void setState(int state);
 
HANDLE getEvent();
};
 
#endif
 
=====================================
 
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "log.h"
#include "EventLock.hpp"
 
const int EventLock::SIGNALED = 1;
 
const int EventLock::NON_SIGNALED = 0;
 
EventLock::EventLock()
{
this->event = CreateEvent(NULL, FALSE, TRUE, NULL);
if (this->event == NULL) 
{
DWORD error = GetLastError();
warn("create event error %d", error);
}
debug("EventLock()");
}
 
EventLock::EventLock(const char* name) 
{
this->event = CreateEvent(NULL, FALSE, FALSE, name);
if (this->event == NULL) 
{
DWORD error = GetLastError();
warn("create event error %d", error);
}
else 
{
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS) 
{
debug("event name %s already exists, use the existed event instead.", name);
}
}
}
 
void EventLock::lock()
{
lock(this->event);
}
 
void EventLock::lock(HANDLE event)
{
DWORD e = WaitForSingleObject(event, INFINITE);
if (e == WAIT_FAILED) 
{
DWORD error = GetLastError();
warn("wait error %d", error);
}
else if(e == WAIT_TIMEOUT) 
{
debug("wait time out");
}
else if(e == WAIT_ABANDONED) 
{
debug("wait abandoned");
}
}
 
void EventLock::unlock()
{
this->unlock(this->event);
}
 
void EventLock::unlock(HANDLE event) 
{
BOOL isr = SetEvent(this->event);
if (! isr) 
{
DWORD error = GetLastError();
warn("release event error %d", error);
}
}
 
void EventLock::setState(int state)
{
if (state == EventLock::SIGNALED) 
{
int error = SetEvent(this->event);
if (! error) 
{
DWORD e = GetLastError();
warn("error to set event object to signaled state");
}
}
else if(state == EventLock::NON_SIGNALED) 
{
int error = ResetEvent(this->event);
if (! error) 
{
DWORD e = GetLastError();
warn("error to set event object to nonsignaled state");
}
}
}
 
HANDLE EventLock::getEvent()
{
return this->event;
}
 
==========================================
 
#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <windows.h>
#include "../Sync.hpp"
 
 
#ifndef TEST_EVENT_LOCK_MESSAGE_DESTINATION
#define TEST_EVENT_LOCK_MESSAGE_DESTINATION
 
class TestEventLockMessageDestination : public Sync
{
private: 
 
int i;
 
public:
TestEventLockMessageDestination()
{
i = 0;
}
 
void add()
{
lock->lock();
i++;
printf("[Producer] message %d\n", this->i);
 
if (i > 0) 
{
this->notify();
}
 
lock->unlock();
}
 
void reduce()
{
lock->lock();
if (i <= 0) 
{
this->wait();
}
 
i--;
printf("[Consumer] message %d\n", i);
 
lock->unlock();
}
};
#endif
 
========================================
 
#include <stdio.h>
#include "../Thread.hpp"
#include "TestEventLockMessageDestination.hpp"
 
#ifndef TEST_EVENT_LOCK_MESSAGE_CONSUMER
#define TEST_EVENT_LOCK_MESSAGE_CONSUMER
 
class TestEventLockMessageConsumer : public Thread 
{
private:
TestEventLockMessageDestination *destination;
 
 
public: 
TestEventLockMessageConsumer()
{
this->destination = NULL;
}
 
void registerConsumer(TestEventLockMessageDestination *destination) 
{
this->destination = destination;
}
 
 
void run() 
{
while (1)
{
if (destination != NULL) 
{
this->destination->reduce();
}
//Sleep(500);
}
}
};
#endif
 
===================================================
 
#include <stdio.h>
#include "../Thread.hpp"
#include "TestEventLockMessageDestination.hpp"
 
#ifndef TEST_EVENT_LOCK_MESSAGE_PRODUCER
#define TEST_EVENT_LOCK_MESSAGE_PRODUCER
 
class TestEventLockMessageProducer : public Thread 
{
private:
TestEventLockMessageDestination *destination;
 
public: 
TestEventLockMessageProducer()
{
this->destination = NULL;
}
 
void registerProducer(TestEventLockMessageDestination *destination) 
{
this->destination = destination;
}
 
void run()
{
while (1) 
{
if (destination != NULL) 
{
destination->add();
}
//Sleep(5000);
}
}
};
#endif
 
==========================================
 
#include "TestEventLockMessageDestination.hpp"
#include "TestEventLockMessageProducer.hpp"
#include "TestEventLockMessageConsumer.hpp"
 
void main()
{
///*
TestEventLockMessageDestination *destination = new TestEventLockMessageDestination();
 
TestEventLockMessageProducer *producer = new TestEventLockMessageProducer();
producer->registerProducer(destination);
producer->start();
 
TestEventLockMessageConsumer *consumer = new TestEventLockMessageConsumer();
consumer->registerConsumer(destination);
consumer->start();
 
ExitThread(0);
 
}
 

Windows下网络编程Socket定义:WINSOCK2.H头文件SOCKET

通信_网络编程_WINDOWS下网络编程_SOCKET编程_VC中WINSOCK2.H头文件SOCKET.doc

 

通信 网络编程 WINDOWS SOCKET 编程 VC WINSOCK2.H 头文件

 

Socket ,形象点可以把它理解为插槽,就像电源插座上面的插孔(不过电源插座上面的插孔有一孔的,还有两孔的,甚至还有三孔的,不知道还有没有四孔的,到目前为止我还没有看过有这么多孔的插座)。电器设备通过一条电源线,一端通过插头插入到能够输送电源的另一端的插座接入另一端,自己的一端也通过插头插入到自己的一个插孔上,将自己和能够输送电源的另一端建立一条物理连接。通过这样的一条物理连接,输送电源的另一端便可以将电源源源不断的输送过来,为电器设备提供电源,电器设备才可以借电力运转。

 

Socket 就类似这种情况,应用程序之间需要通信,就需要建立连接(这里的连接不是逻辑上的连接,而是物理上的连接,无线在这里也暂且把它归为是物理上的连接,只是连接的媒介不同而已)。现在假设连接的线有了,两端的节点也有了,并且连接的线两端也都套了一个能插入的插头,要实现通信,通信的应用程序还需要分别提供一个插槽以便将两头的插头都插入到插槽,这就是 SOCKET !

 

以上只是举了些例子以便更形象的理解 Socket ,它只是逻辑上的概念, Sockets 也有专门的协议规范来标准化。在 rfc1928.txt 中,根据 OSI 模型, SOCKET 在概念上是一种位于应用层与传输层之间的中间层的网络传输协议。在实际实现上,例如在不同平台上的 Socket 的实现也有些差别。

 

在 WINDOWS 平台上, Socket 实现是在动态链接库 ws2_32.dll 中, VC 中的头文件 WINSOCK2.H 及 WINSOCK.H 有定义。

 

查看头文件定义,在 WINSOCK2.H 头文件中, SOCKET 由一个简单的类型定义将 SOCKET 定义为一个 u_int 类型,而 u_int 类型其实就是一个 unsigned int 类型:

 

/*

  * The new type to be used in all

  * instances which refer to sockets.

  */

typedef u_int           SOCKET;

 

 

typedef unsigned int    u_int;

 

 

 

创建 SOCKET

#if INCL_WINSOCK_API_PROTOTYPES

WINSOCK_API_LINKAGE

SOCKET

WSAAPI

socket(

    int af,

    int type,

    int protocol

    );

#endif // INCL_WINSOCK_API_PROTOTYPES

 

INCL_WINSOCK_API_PROTOTYPES 定义

 

#ifndef INCL_WINSOCK_API_PROTOTYPES

#define INCL_WINSOCK_API_PROTOTYPES 1

#endif

 

#ifndef INCL_WINSOCK_API_TYPEDEFS

#define INCL_WINSOCK_API_TYPEDEFS 0

#endif

 

 

WINSOCK_API_LINKAGE 定义

 

#ifndef WINSOCK_API_LINKAGE

#ifdef DECLSPEC_IMPORT

#define WINSOCK_API_LINKAGE DECLSPEC_IMPORT

#else

#define WINSOCK_API_LINKAGE

#endif

#endif

 

DECLSPEC_IMPORT 定义(在 WINNT.H 头文件中)

#if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC) || defined(_M_IA64)) && !defined(MIDL_PASS)

#define DECLSPEC_IMPORT __declspec(dllimport)

#else

#define DECLSPEC_IMPORT

#endif

 

WSAAPI 定义

#ifdef WIN32

 

#define WSAAPI                  FAR PASCAL

。。。

。。。

#else /* WIN16 */

 

#define WSAAPI                  FAR PASCAL

。。。

。。。

#endif  /* WIN32 */

 

创建 SOCKET 函数 socket 返回创建的 SOCKET ,类型如上定义。此函数传入三个参数:

 

int af,

int type,

int protocol

 

第一个参数 af 传入的是地址家族( address family ) , 也就是地址簇或者协议簇。

该参数在不同的系统下参数不一定相同,另外注意不同的版本可以使用的参数也不相同,可以参考相关文档。这里列出了所有要求的参数可用值。

 

参数 a. 地址族(与 TCP/IP 协议下的协议族等价)可以使用的参数如下

#define AF_UNIX         1               /* local to host (pipes, portals) */

#define AF_INET           2                 /* internetwork: UDP, TCP, etc. */

#define AF_IMPLINK      3               /* arpanet imp addresses */

#define AF_PUP          4               /* pup protocols: e.g. BSP */

#define AF_CHAOS        5               /* mit CHAOS protocols */

#define AF_NS           6               /* XEROX NS protocols */

#define AF_IPX          AF_NS           /* IPX protocols: IPX, SPX, etc. */

#define AF_ISO          7               /* ISO protocols */

#define AF_OSI          AF_ISO          /* OSI is ISO */

#define AF_ECMA         8               /* european computer manufacturers */

#define AF_DATAKIT      9               /* datakit protocols */

#define AF_CCITT        10              /* CCITT protocols, X.25 etc */

#define AF_SNA          11              /* IBM SNA */

#define AF_DECnet       12               /* DECnet */

#define AF_DLI          13              /* Direct data link interface */

#define AF_LAT          14              /* LAT */

#define AF_HYLINK       15              /* NSC Hyperchannel */

#define AF_APPLETALK    16              /* AppleTalk */

#define AF_NETBIOS      17              /* NetBios-style addresses */

#define AF_VOICEVIEW    18              /* VoiceView */

#define AF_FIREFOX      19              /* Protocols from Firefox */

#define AF_UNKNOWN1     20              /* Somebody is using this! */

#define AF_BAN          21              /* Banyan */

#define AF_ATM          22              /* Native ATM Services */

#define AF_INET6        23              /* Internetwork Version 6 */

#define AF_CLUSTER      24              /* Microsoft Wolfpack */

#define AF_12844        25              /* IEEE 1284.4 WG AF */

#define AF_MAX          26

AF_UNIX // 表示 Unix 内部协议

AF_NS // 表示使用的是 Xerox NS 协议族

AF_IMPLINK// 表示 IMP 连接层

另外 AF_LOCAL 是用于 Unix/Linux 系统中本机进程间通信

 

 

第二个参数传入的是 SOCKET 类型,可传入的 SOCKET 类型如下:

 

参数 b.Socket 类型

可以取如下的一些值:

SOCK_STREAM 流套接字

SOCK_DGRAM 数据报套接字

SOCK_RAW 未加工套接字(可以用它来接收原始的数据包,即不经过传输层的,常用来抓包)

SOCK_SEQPACKET 顺序包套接字

#define SOCK_STREAM     1               /* stream socket */

#define SOCK_DGRAM      2               /* datagram socket */

#define SOCK_RAW        3               /* raw-protocol interface */

#define SOCK_RDM        4               /* reliably-delivered message */

#define SOCK_SEQPACKET  5               /* sequenced packet stream */

 

第三个参数传入的是协议类型,可传入的协议类型如下:

 

参数 c.Socket 使用的协议类型

通常将此设为 0 即 IPPROTO_IP ,是因为协议类型可以根据 Socket 的类型来确定,比如 Sock_STREAM 就是使用 TCP 协议,而 SOCK_DGRAM 就是使用 UDP 协议。

其他的类型还有 :

#define IPPROTO_ICMP            1               /* control message protocol */

#define IPPROTO_IGMP            2               /* internet group management protocol */

#define IPPROTO_GGP             3               /* gateway^2 (deprecated) */

#define IPPROTO_TCP             6               /* tcp */

#define IPPROTO_PUP             12              /* pup */

#define IPPROTO_UDP             17              /* user datagram protocol */

#define IPPROTO_IDP             22              /* xns idp */

#define IPPROTO_ND              77              /* UNOFFICIAL net disk proto */

#define IPPROTO_RAW             255             /* raw IP packet */

#define IPPROTO_MAX             256

 

 

网络编程-SOCKET-创建SOCKET-WINDOWS下socket函数声明问题

今天翻了下VC下SOCKET头文件WINSOCK2.H,又看了下socket函数的声明:

 

#if INCL_WINSOCK_API_PROTOTYPES
WINSOCK_API_LINKAGE
SOCKET
WSAAPI
socket(
    int af,
    int type,
    int protocol
    );
#endif // INCL_WINSOCK_API_PROTOTYPES

 

注意到#if INCL_WINSOCK_API_PROTOTYPES这个条件编译,通常我们是通过#if, #ifdef或者#ifndef来判断选择哪一部分来编译以及在#include时解决因为重复包含的问题。

 

但这里的#if INCL_WINSOCK_API_PROTOTYPES这个条件编译是啥意思?在WINSOCK2.H文件靠近开头的位置有有如下定义:

 

#ifndef INCL_WINSOCK_API_PROTOTYPES
#define INCL_WINSOCK_API_PROTOTYPES 1
#endif

 

也就是INCL_WINSOCK_API_PROTOTYPES始终被替换为1,那么既然为1,干嘛还需要这样一个条件?

 

 

Windows CryptoAPI

// win32-test.cpp : 定义控制台应用程序的入口点。
// 
// Defines the entry point for the console 
// application.

#include "stdafx.h"


#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <conio.h>
#include <atlenc.h>

#include "encrypt.h"

// Link with the Advapi32.lib file.
#pragma comment (lib, "advapi32")



typedef struct {
    BYTE * keyData;
    int keyDataLen;
} B_RSAW;

typedef struct 
{
    char *keyData;
    int keDataLen;
} RSAW;

B_RSAW* RSA_key_w() 
{
    HCRYPTPROV hCryptProv = NULL; // handle to a cryptographic service provider (CSP)
    //---------------------------------------------------------------
    // Get the handle to the default provider. 
    // #param pszProvider  Cryptographic Provider Names
    //     MS_ENHANCED_PROV  "Microsoft Enhanced Cryptographic Provider v1.0"
    CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
    if(CryptAcquireContext(
        &hCryptProv, 
        NULL, 
        MS_ENHANCED_PROV, // "Microsoft Enhanced Cryptographic Provider v1.0"
        PROV_RSA_FULL, 
        CRYPT_NEWKEYSET))
    {
        _tprintf(
            TEXT("A cryptographic provider has been acquired. \n"));
    }
    else
    {
        return NULL;
    }

    HCRYPTKEY hKey;// handle of the key
    if(CryptGenKey(
          hCryptProv, 
          AT_KEYEXCHANGE, 
          CRYPT_EXPORTABLE, 
          &hKey))
    {
         printf("A session key has been created.\n");
    } 
    else
    {
          printf("Error during CryptGenKey.\n"); 
          exit(1);
    }

    DWORD dwTempPriLen;
    int r = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, NULL, NULL, &dwTempPriLen);


    BYTE *pbTempPriData = (BYTE *)malloc(dwTempPriLen+1);
    r = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, NULL, pbTempPriData, &dwTempPriLen);

    //-------------------------------------------------------------------
    //  The key created can be exported into a key BLOB that can be
    //  written to a file.
    //  ...
    //  When you have finished using the key, free the resource.
    if (!CryptDestroyKey(hKey))
    {
          printf("Error during CryptDestroyKey.\n"); 
          exit(1);
    }
    if (! CryptReleaseContext(hCryptProv, 0)) 
    {
        printf("Error during CryptReleaseContext.\n"); 
          exit(1);
    }
    B_RSAW *rsa = (B_RSAW *) malloc(sizeof(B_RSAW));
    rsa->keyData = pbTempPriData;
    rsa->keyDataLen = dwTempPriLen;
    return rsa;
}

void RSA_key_write_RSAPrivateKey_W(const char* fn, B_RSAW* rsa) 
{
    FILE *fp = NULL;
    fp = fopen(fn, "wb");
    if (fp == NULL) {
        fprintf(stderr,"%s open error", fn);
    }
    printf("file %s opened...\n", fn);
    fwrite(rsa->keyData, 1, rsa->keyDataLen+1, fp);
    fclose(fp);
}

RSAW* RSA_key_base64_w(B_RSAW *rsa) 
{
    //B_RSAW *rsa = RSA_key_w();
    int len = Base64EncodeGetRequiredLength(rsa->keyDataLen, ATL_BASE64_FLAG_NONE);
    LPSTR szDest = (LPSTR) malloc(len + 1);
    memset(szDest, 0, len + 1);
    
    Base64Encode(rsa->keyData, rsa->keyDataLen, szDest, &len, ATL_BASE64_FLAG_NONE );

    
    
    RSAW *_rsa = (RSAW *) malloc(sizeof(RSAW));
    _rsa->keyData = szDest;
    _rsa->keDataLen = len + 1;
    return _rsa;
}

void RSA_key_write_RSAPrivateKey_base64_W(const char* fn, RSAW* rsa)
{
    FILE *fp2 = NULL;

    fp2 = fopen(fn, "wb");
    if (fp2 == NULL) {
        fprintf(stderr,"%s open error", fn);
        return;
    }
    //fwrite(rsa->keyData, 1, rsa->keyDataLen+1, fp);
    fprintf(fp2, "%s", rsa->keyData);
    //fclose(fp);
    fclose(fp2);
}


int _tmain(int argc, _TCHAR* argv[])
{
    /*
    if(argc < 3)
    {
        _tprintf(TEXT("Usage: <example.exe> <source file> ")
            TEXT("<destination file> | <password>\n"));
        _tprintf(TEXT("<password> is optional.\n"));
        _tprintf(TEXT("Press any key to exit."));
        _gettch();
        return 1;
    }
    */

    B_RSAW *rsa = RSA_key_w();

    char *fn = "D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\test-g-win.key";
    RSA_key_write_RSAPrivateKey_W(fn, rsa);

    RSAW *_rsa = RSA_key_base64_w(rsa);
    char *fn2 = "D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\test-g-2-win.key";
    RSA_key_write_RSAPrivateKey_base64_W(fn2, _rsa);

    /*
    LPTSTR pszSource = NULL; 
    LPTSTR pszDestination = NULL; 
    LPTSTR pszPassword = NULL;

    pszSource = L"D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\plain-text.txt";
    pszDestination = L"D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\encrypt-text.txt";
    pszPassword = L"yihaodian";

    //---------------------------------------------------------------
    // Call EncryptFile to do the actual encryption.
    if(MyEncryptFile(pszSource, pszDestination, pszPassword))
    {
        _tprintf(
            TEXT("Encryption of the file %s was successful. \n"), 
            pszSource);
        _tprintf(
            TEXT("The encrypted data is in file %s.\n"), 
            pszDestination);
    }
    else
    {
        MyHandleError(
            TEXT("Error encrypting file!\n"), 
            GetLastError()); 
    }
    */
    return 0;
}

 

 

 

有关 SOCKET 资料可参考:

维基百科 http://zh.wikipedia.org/wiki/SOCKS

IETF RFC 1928, rfc1928.txt, SOCKS Protocol Version 5

IETF RFC 1929, rfc1929.txt, Username/Password Authentication for SOCKS V5

各平台( Linux 、 Unix 、 Windows 等)对 SOCKET 的实现

互联网传输协议的性能优化: http://shop.zte.com.cn/main/include/showemagazinearticle.jsp?articleId=369&catalogId=12165

 

 

VC下相关工具

lib

>LIB.EXE /LIST liblog_static.lib

Microsoft (R) Library Manager Version 6.00.8168

Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

 

.\Debug\SocketAppender.obj

.\Debug\LoggerWrapper.obj

.\Debug\log.obj

.\Debug\GenericAppender.obj

.\Debug\FileAppender.obj

.\Debug\AsynchronizedAppender.obj

.\Debug\Appender.obj

.\Debug\StandardAppender.obj

 

Makefile

Windows Make file(VC, NMAKE)

 

>NMAKE /f "nmake_test.mak" CFG="nmake_test - Win32 Debug" /y /d

 

@echo "$(OS)"

 

!IF "$(OS)" == "Windows_NT"

NULL=

!ELSE 

NULL=nul

!ENDIF

 

 

 

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

 

INCLUDE_MYSQL=D:\usr\srv\mysql51\include

LIB_MYSQL=D:\usr\srv\mysql51\lib\debug

 

 

liblog.lib: clean

$(CL) /GX /W3 /I $(INCLUDE) /c /Fo$(DEBUG)/ ../SQLException.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../Mysql.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../Connection.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../MysqlConnection.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../MysqlStatement.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../MysqlResultSet.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../Mysql.cpp

$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ MysqlTest.cpp

#$(CL) /GX /W3 /I $(INCLUDE) /c StdAfx.cpp

#$(CL) /GX /W3 /I $(INCLUDE) /c *.cpp

#$(CL) /GX /W3 /I $(INCLUDE) /c /Fo$(DEBUG)/ *.cpp

 

#lib /nologo log.obj /out:./liblog.lib 

$(LINK) /LIBPATH:$(LIB) /LIBPATH:$(LIB_LIB_LOG) /LIBPATH:$(LIB_MYSQL) /OUT:$(DEBUG)/MysqlTest.exe $(DEBUG)/*.obj

#$(LINK) /DLL /LIBPATH:$(LIB) /OUT:$(DEBUG)/liblog.dll *.obj

#$(LINK) /DLL /LIBPATH:$(LIB) /OUT:$(DEBUG)/liblog.dll $(DEBUG)/*.obj

# $(LINK) *.obj /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib"

cp ../liblog.dll $(DEBUG)/

 

clean:

rm -Rf ./*.bak

rm -Rf ./*.o

rm -Rf ./*.obj

rm -Rf ./*.exe

rm -Rf ../Debug/*

 

 

 

 

 

 

VC命令行环境下生成.DLL, .LIB库

 

创建make文件

       Makefile.nmake

 

make文件内容

 

DEBUG=./Debug

 

liblog.lib:

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

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

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

#lib /nologo log.obj /out:./liblog.lib 

#"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /DLL /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:$(DEBUG)/liblog.dll log.obj

"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /DLL /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:$(DEBUG)/liblog.dll *.obj

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

 

命令行下MAKE

 

nmake /f Makefile.nmake

wxWidgets

第一个简单的程序

下面是一个完整的程序,这是一个C++程序,这个程序中没有看到有入口函数。

#include "wx/wx.h"

IMPLEMENT_APP(wxApp)

 $ `wx-config --cxx` -c `wx-config --cxxflags --unicode=yes --static=no --toolkit=osx_cocoa --version=3.0` window_test.cpp -o window_test.o

 

$ `wx-config --cxx` -o window_test window_test.o `wx-config --unicode=yes --static=no --toolkit=osx_cocoa --version=3.0 --libs core,base`

 

可以通过以下命令看下程序是怎样的

$ `wx-config --cxx` -E `wx-config --cxxflags --unicode=yes --static=no --toolkit=osx_cocoa --version=3.0` window_test.cpp -o window_test.i

 

 * int main(int argc, char **argv) 

 * { 

 *   ; 

 *   ; 

 *   return wxEntry(argc, argv); 

 * } 

 *

 * wxApp& wxGetApp() 

 * { 

 *   return *static_cast<wxApp*>(wxApp::GetInstance()); 

 * } 

 * wxAppConsole *wxCreateApp() 

 * { 

 *   wxAppConsole::CheckBuildOptions("3" "." "0" " (" "wchar_t" ",compiler with C++ ABI " "1002" ",wx containers" ",compatible with 2.8" ")", "your program"); 

 *   return new wxApp; 

 * } 

 * wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);

 

窗口

#include "wx/wx.h"

class MyApp : public wxApp
{
public:
  virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
  MyFrame(const wxString& title);

	void OnExit(wxCommandEvent& WXUNUSED(event)) { Close(); }
private:
	
  wxDECLARE_EVENT_TABLE();
};

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_MENU(wxID_EXIT, MyFrame::OnExit)
wxEND_EVENT_TABLE()

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
  if (! wxApp::OnInit())
    return false;

  MyFrame *frame = new MyFrame("主窗口");
  frame->Show(true);

  return true;
}

MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(500, 400))
{
	
}

 

 

工具

 

wx-config

 

 

分享到:
评论

相关推荐

    Windows编程课件 Windows编程课件 Windows编程课件

    在Windows编程领域,开发者需要掌握一系列技术和工具来创建应用程序,这些应用程序可以与操作系统无缝交互,提供用户友好的界面和高效的功能。本课件主要聚焦于Windows编程的核心概念和技术,通过以下章节来深入探讨...

    Windows编程基础.pdf

    Windows 编程基础 本书将着重介绍 Windows 应用程序在 C# 环境下的开发应用,涵盖了 C# 编程基础和抽象的软件设计思想,为期望快速进入 C# Windows 程序设计领域的读者提供了一个适合的入门级教材。 课程简介 ...

    windows编程相关书籍

    在IT领域,Windows编程是开发桌面应用程序的重要组成部分。Windows编程主要涉及使用Microsoft的API(应用程序接口)和其他开发工具,如Visual C++(简称VC),来创建可以在Windows操作系统上运行的应用程序。以下是...

    Windows编程新手教程

    在Windows编程领域,新手往往面临着许多挑战,但随着丰富的学习资源和适当的指导,这些挑战将变得不再难以克服。本教程“Windows编程新手教程”旨在为初学者提供一个全面且易于理解的学习路径,涵盖基础概念、关键...

    windows编程API手册

    《Windows编程API手册》是一本深入探讨Windows操作系统编程核心的宝贵资源,主要涵盖了Windows API函数的使用和功能解析。Windows API是开发Windows应用程序的基础,它提供了丰富的函数接口,供程序员调用来实现各种...

    windows编程pdf课件

    《Windows编程基础与实践》PDF课程资料是一份全面介绍Windows编程的宝贵资源,尤其适合初学者入门学习。这份课件涵盖了从基础知识到高级技术的全方位内容,旨在帮助读者建立起扎实的Windows程序设计基础。 首先,...

    windows编程 推箱子游戏

    《Windows编程:推箱子游戏开发详解》 在计算机科学领域,Windows编程是一项基础且重要的技能,它涉及到系统级的交互和应用开发。本教程将通过一个经典的“推箱子”游戏来深入探讨Windows编程的原理与实践。推箱子...

    Windows编程入门——字节跳动.pptx

    Windows 编程入门 Windows 编程入门是指使用微软的 Windows 操作系统进行软件开发的入门指南。本指南涵盖了 Windows 编程的基本理论、开发工具和框架、 Demo 实战等方面的知识点。 Windows 操作系统 Windows 操作...

    VC windows编程基础

    VC++编程基础主要涵盖Windows API和MFC框架的使用,是初学者进入Windows编程领域的基础知识。Windows编程涉及一系列概念和技术,下面将详细阐述这些知识点。 首先,了解Windows编程基础至关重要,这包括可视化程序...

    Windows编程启示录.pdf

    根据提供的文件信息,“Windows编程启示录.pdf”似乎是一本深入探讨Windows操作系统内部工作原理和技术细节的书籍。本书作者Raymond Chen是微软公司的资深员工,在Windows操作系统的发展历程中扮演了重要角色。下面...

    windows游戏编程 第二章 windows编程模型 实例

    在Windows游戏编程的世界里,Windows编程模型是构建游戏的基础,它是所有交互式应用程序的核心。这一章节将深入探讨如何利用Microsoft的Visual C++ 6.0(VC++6.0)来实现这一模型,并通过实例来加深理解。让我们一...

    Windows编程 ppt课件。

    《Windows编程基础详解》 Windows编程是计算机科学领域的一个重要分支,主要涉及在Windows操作系统平台上设计和开发应用程序。本教程将深入浅出地介绍Windows编程的基础知识,包括其历史、核心概念以及用户界面的...

    国软 Windows编程实践

    武大国软 Windows编程实践 三个项目和实验报告 高分作业 包括:实验一:用Visual C++开发简单的WinAPI程序 实验二:用MFC开发计算器程序 实验三:用MFC开发简单文本查看程序 和总的实验报告

    C#Windows编程.pdf

    根据提供的文件信息,“C#Windows编程.pdf”似乎是一份关于使用C#进行Windows应用程序开发的技术文档。接下来将根据这份文档的标题、描述以及部分可见内容,深入探讨与C# Windows编程相关的几个关键知识点。 ### C#...

    C++,Windows编程

    标题 "C++,Windows编程" 涉及到的是利用C++这一强大编程语言进行Windows平台下的应用程序开发。C++是一种通用、面向对象的编程语言,以其高效性、灵活性和广泛的库支持而闻名。Windows编程则涉及到如何利用Windows ...

    C#windows编程

    《C# Windows编程》这本书是针对使用C#语言进行Windows应用程序开发的专业指南。它涵盖了从基础知识到高级技术的全面内容,旨在帮助读者掌握利用C#在Windows平台上构建高效、稳定和用户友好的应用程序的技能。 在C#...

    白话windows编程.rar

    《白话Windows编程》是一本面向初学者和中级程序员的指南,旨在用通俗易懂的语言讲解Windows操作系统下的程序开发技术,主要关注C++语言在Windows平台的应用。这本书深入浅出地介绍了如何使用C++进行Windows API编程...

    windows编程(第6版)

    ### Windows编程(第6版) #### 书籍概览与作者介绍 《Windows编程》第六版是Charles Petzold的经典著作,专注于编写适用于Windows 8的Metro风格应用。本书由Microsoft Press出版,是一本针对消费者预览版的电子书...

    Windows编程循序渐进 随书光盘

    《Windows编程循序渐进》是一本针对初学者和进阶者设计的教程,它旨在帮助读者逐步掌握Windows操作系统下的程序开发技术。该书随附的光盘包含了丰富的源代码和示例程序,使得理论学习与实践操作相结合,极大地提升了...

Global site tag (gtag.js) - Google Analytics