存档在 2009年11月

非静态类成员函数指针解决方案

2009年11月5日

众所周知,我们无法定义一个指向类的非静态成员函数。在Borland C/C++中,Bolrand公司添加了关键字__closure用来定义这种特殊的指针。在Visual C/C++中虽然也有解决方染,但是使用麻烦,且不易于使用。网络上下存在很多解决方案,但作者均未看到较为好用的解决方案。

本文即提供一种于x86-32平台下的解决方案,使用方式类似于Borland C/C++,十分方便。代码在Borland C/C++ 5.82Microsoft C/C++ 14.0 (Visual C/C++ 8.0)下测试通过。


#include<stdio.h>
#include<stddef.h>

class _Object{};

#if defined(SetEventCall)||defined(CallEvent)||defined(DefineEvent)
    #error SetEventCall,CallEvent,DefineEvent 已经定义
#endif//

#ifdef __BORLANDC__

    #define SetEventCall(event_obj,event_func)              event_obj=event_func
    #define CallEvent(event_obj)                            event_obj
    #define DefineEvent(name,result,intro)                  result (__closure *name)intro

#else

    #pragma warning(disable:4311)

    template <typename T> struct EventFunc
    {
        unsigned __int32 this_address;
        unsigned __int32 func_address;

        _Object *This;
        T Func;

        EventFunc()
        {   
            this_address=offsetof(EventFunc,This);
            this_address+=(unsigned __int32)this;

            func_address=offsetof(EventFunc,Func);
            func_address+=(unsigned __int32)this;
        }
    };

    #define SetEventCall(event_obj,event_func)      {   \
                                                        unsigned __int32 this_address=event_obj.this_address;   \
                                                        unsigned __int32 func_address=event_obj.func_address;   \
                                                        \
                                                        {   \
                                                            __asm mov eax,this_address  \
                                                            __asm mov ebx,this  \
                                                            __asm mov [eax],ebx \
\
                                                            __asm mov eax,func_address  \
                                                            __asm mov ebx,event_func    \
                                                            __asm mov [eax],ebx \
                                                        }   \
                                                    }

    #define CallEvent(event_obj)                    (event_obj.This->*(event_obj.Func))             //(*(event_obj.This).*(event_obj.Func))

    #define DefineEvent(name,result,intro)          EventFunc<result (_Object:: *)intro> name;
#endif//__BORLANDC__

class Button
{
public:

    DefineEvent(OnClick,void,(Button *,int));     //定义事件,原型为: void OnClick(Button *,int)

public:

    Button()
    {
        printf("Button this=%p\n",this);
    }

    void TestButtonClick()
    {
        CallEvent(OnClick)(this,0);               //呼叫OnClick,原型为: OnClick(this,0)
    }
};

class Test
{
    Button *button;

public:

    void OnButtonClick(Button *but,int)
    {
        printf("Test::OnButtonClick,this=%p,but=%p\n",this,but);
    };

public:

    Test()
    {
        printf("Test this=%p\n",this);

        button=new Button;

        SetEventCall(button->OnClick,OnButtonClick);              //设定button->OnClick事件的处理函数为OnButtonClick

        button->TestButtonClick();
    }
};

void main(int,char **)
{
    Test *test;

#ifdef __BORLANDC__
    printf("Compiler: Borland C/C++ or Turbo C/C++ %d.%d%d\n",(__BORLANDC__>>8),((__BORLANDC__&0xF0)>>4),(__BORLANDC__&0x0F));
#endif
#ifdef _MSC_VER
    printf("Compiler: Microsoft C/C++ %.2f (Visual C/C++ %.2f)\n",_MSC_VER/100.f,_MSC_VER/100.f-6);
#endif//

    printf("Compile Time: %s %s\n\n",__DATE__,__TIME__);

    test=new Test;

    delete test;
}

Compiler: Borland C/C++ or Turbo C/C++ 5.82
Compile Time: Dec 23 2006 17:34:48

Test this=00902D50
Button this=00902D64
Test::OnButtonClick,this=00902D50,but=00902D64

Compiler: Microsoft C/C++ 14.00 (Visual C/C++ 8.00)
Compile Time: Dec 23 2006 17:34:00

Test this=003826D0
Button this=00382700
Test::OnButtonClick,this=003826D0,but=00382700

DirectDraw7初始化

2009年11月5日

//—————————————————————————
#include <windows.h>
#include <ddraw.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#pragma hdrstop

//—————————————————————————

#pragma argsused

#define GAMENAME    “DirectDraw 7 窗口示例”
#define ScreenWidth 640
#define ScreenHigh  480
#define ScreenColor 32
#define WINDOWSTYLE WS_VISIBLE|WS_THICKFRAME|WS_SYSMENU|WS_MINIMIZEBOX

IDirectDraw         *_DirectDraw=NULL;
IDirectDraw7        *DirectDraw;
IDirectDrawSurface7 *PrimarySurface;
DDSURFACEDESC2      ddsd;

bool InitDirectDraw(HWND hwnd)
{
if(DirectDrawCreate(NULL,&_DirectDraw,NULL)!=DD_OK)return(false);
if(_DirectDraw->QueryInterface(IID_IDirectDraw7,(void **)&DirectDraw)!=DD_OK)
{
_DirectDraw->Release();
return(false);
}

if(DirectDraw->SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)!=DD_OK)
{
DirectDraw->Release();
_DirectDraw->Release();
return(false);
}

if(DirectDraw->SetDisplayMode(ScreenWidth,ScreenHigh,ScreenColor,0,0)!=DD_OK)
{
DirectDraw->Release();
_DirectDraw->Release();
return(false);
}

memset(&ddsd,0,sizeof(DDSURFACEDESC2));

ddsd.dwSize             =sizeof(DDSURFACEDESC2);
ddsd.dwFlags            =DDSD_CAPS;
ddsd.ddsCaps.dwCaps     =DDSCAPS_PRIMARYSURFACE;

if(DirectDraw->CreateSurface(&ddsd,&PrimarySurface,NULL)!=DD_OK)
{
DirectDraw->Release();
_DirectDraw->Release();
return(false);
}

return(true);
}

void CloseDirectDraw()
{
PrimarySurface->Release();
DirectDraw->Release();
_DirectDraw->Release();
}

HWND InitWindow(HINSTANCE hinstance)
{
HWND hwnd;
WNDCLASSEX wc;

wc.cbSize=sizeof(WNDCLASSEX);
wc.style=0;
wc.lpfnWndProc=(WNDPROC)DefWindowProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hinstance;
wc.hIcon=LoadIcon(NULL,NULL);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)COLOR_BACKGROUND;
wc.lpszMenuName=0;
wc.lpszClassName=”绝情创作群”;
wc.hIconSm=LoadIcon(hinstance,IDI_APPLICATION);

RegisterClassEx(&wc);
hwnd=CreateWindowEx(NULL,”绝情创作群”,GAMENAME,WINDOWSTYLE,0,0,ScreenWidth,ScreenHigh,0,0,hinstance,0);

ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);

return(hwnd);
}

WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;

hwnd=InitWindow(hInstance);
InitDirectDraw(hwnd);

//………….

CloseDirectDraw();
return(0);
}
//—————————————————————————

C++常见错误之一   new[]与delete[]

2009年11月5日

int *data;

data=new int[100];

delete data;

以上程序在Visual C++ 6.0中是正确的,然而在最新的ANSI/ISO C++标准中,它却是错误的。

在以往的日子里,我也一直这么写。昨日在使用CodeGuard除错,发现在delete data一行时报告资源类型不匹配。一查CodeGuard报告,提示使用new []形式创建的资源要使用delete []释放。所以正确的程序应该如下:

int *data;

data=new int[100];

delete[] data;

以上的程序在 Borland C++ Builder 6 中测试通过,CodeGuard对未修改的错误程序报告如下:

Error 00019. 0x350010 (Thread 0x04F4):
Resource type mismatch: a(n) object was expected.
delete(0x00CF5244)

Call Tree:
0x004011C0(=NDTest.exe:0x01:0001C0) D:\Program Files\Borland\CBuilder6\Projects\NDTest\MainUnit.cpp#15
0x3266FFB3(=CC3260.DLL:0x01:06EFB3)

The object array (0x00CF5244) [size: 400 bytes] was created with new[]
Call Tree:
0x004011B4(=NDTest.exe:0x01:0001B4) D:\Program Files\Borland\CBuilder6\Projects\NDTest\MainUnit.cpp#13
0x3266FFB3(=CC3260.DLL:0x01:06EFB3)

——————————————
Functions called:
delete (25 times)
realloc (1 times)
memcpy (1 times)
delete[] (2 times)
free (15 times)
new[] (15 times)
new (29 times)
calloc (5 times)
malloc (9 times)
Resource types used:
object array (15 allocs, 14 max)
object (29 allocs, 17 max)
memory block (15 allocs, 10 max)
Modules used:
00400000 05/13/2003 10:56:46 D:\Program
Files\Borland\CBuilder6\Projects\NDTest\NDTest.exe
0CD00000 01/30/2002 17:38:38 D:\PROGRA~1\Borland\CBUILD~1\Bin\CG32.DLL
32600000 01/30/2003 06:04:00 D:\PROGRA~1\Borland\CBUILD~1\Bin\CC3260.DLL
65D20000 07/22/2002 12:05:04 C:\WINNT\System32\USP10.dll
6C330000 07/22/2002 12:05:04 C:\WINNT\System32\LPK.DLL
75E00000 07/22/2002 12:05:04 C:\WINNT\System32\IMM32.DLL
77D90000 11/11/2002 15:33:44 C:\WINNT\system32\ADVAPI32.DLL
77DF0000 11/04/2002 10:58:50 C:\WINNT\system32\USER32.DLL
77E60000 11/04/2002 10:58:54 C:\WINNT\system32\KERNEL32.DLL
77F40000 07/23/2002 16:34:08 C:\WINNT\system32\GDI32.dll
77F80000 04/04/2003 15:47:22 C:\WINNT\system32\ntdll.dll
786F0000 11/20/2002 16:53:24 C:\WINNT\system32\RPCRT4.dll
==========================================

Win32多线程C程序示例

2009年11月5日

// Win32 多线程示例
// 网址: http://www.hyzgame.com
//————————————————————————————————–
#include <windows.h>
#include <iostream.h>
//————————————————————————————————–
DWORD WINAPI Print123(void *)
{
int i;

for(i=0;i<10;i++)
cout<<“123″<<endl;

return(0);
}

//————————————————————————————————–
DWORD WINAPI PrintABC(void *)
{
int i;

for(i=0;i<10;i++)
cout<<“ABC”<<endl;

return(0);
}
//————————————————————————————————–
DWORD WINAPI Printabc(void *)
{
int i;

for(i=0;i<10;i++)
cout<<“abc”<<endl;

return(0);
}
//————————————————————————————————–
int main(int argc,char **argv)
{
HANDLE handles[3];
DWORD  ids[3];

handles[0]=CreateThread(NULL,0,Print123,NULL,NULL,&ids[0]);
handles[1]=CreateThread(NULL,0,PrintABC,NULL,NULL,&ids[1]);
handles[2]=CreateThread(NULL,0,Printabc,NULL,NULL,&ids[2]);

WaitForMultipleObjects(3,handles,true,INFINITE);

CloseHandle(handles[0]);
CloseHandle(handles[1]);
CloseHandle(handles[2]);

return(0);
}

堆排序算法C源程序

2009年11月5日

#include<stdio.h>
#include<stdlib.h>

void isift(int *p,int i,int n)
{
int j,t;

t=p[i];
j=2*(i+1)-1;

while(j<=n)
{
if((j<n)&&(p[j]<p[j+1]))j++;

if(t<p[j])
{
p[i]=p[j];
i=j;
j=2*(i+1)-1;
}
else j=n+1;
}

p[i]=t;
return;
}

void pihap(int *p,int n)
{
int i,mm,t;

mm=n/2;
for(i=mm-1;i>=0;i–)
isift(p,i,n-1);

for(i=n-1;i>=1;i–)
{
t=p[0];
p[0]=p[i];
p[i]=t;

isift(p,0,i-1);
}

return;
}

void main(int argc,char *argv[])
{
int i;
int data[32];

printf(“未排序:”);
for(i=0;i<32;i++)
printf(“%d,”,data[i]=rand()%100);

pihap(data,32);

printf(“\n已排序:”);
for(i=0;i<32;i++)
printf(“%d,”,data[i]);
}

如何安装Turbo C++ 3.0 for DOS

2009年11月5日

一、运行安装盘下的Install.EXE,运行后界面如下:

Image1

二、按Enter键继续

Image2

三、此时安装程序会要求你输入安装盘的盘符,输入后按回车

Image3

四、此时输入安装文件的路径,一般直接按回车

Image4

五、此页是安装选项,第一项是选择安装后的路径,第二项不用管它,最后选择第三项按回车

如何使用“Dev-C++ 5.0 (4.9.6.0)”

2009年11月5日

Dev-C++ 5.0是Bloodshed软件公司于2002年9月26日推出的一个基于MingW(即GNU C/C++的Win32版)的微型C/C++开发工具。

由于使用了GNU C/C+内核,所以在做软件移植时非常的方便,你可以方便的将一个程序移植到任意一个有GNU C/C++的平台。而 且由于基于GNU C/C++的开放源代码软件很多,所以使用Dev-C++是一个很好的选择。但由于它的调试不便,帮助不全等问题,也使得它在推广上举步艰难,远比不上 Borland C/C++、OpenWatcom C/C++这两个同是免费的编译器。

一、下载

你可以从官方网站下载。由于它是个GNU软件,所以在它的使用上,您需要遵守GPL协议。

官方网站

二、安装

运行安装程序后,界面如下:

Image1

这页是GPL协议,如果您同意的话,点“I Agree”按钮可以继续安装,按“Cancel”放弃安装。

Image2

在这一界面上要以选择需要安装的文件,由于这个软件仅33MB,所以我们可以直接点击“Next >”继续安装。

Image3

在这一界面上选择安装目录,选好后按“Install”开始安装。

三、选择界面语种

运行Dev-C++ 5.0后,界面如下:

Image4

在Tools菜单选择“Enviroment Options”,在出现的对话框的“Interface”页内,在“Language”处选择“Chinese”。如下图。

Image6

点击“OK”后界面将变为中文,如下图:

四、建立项目

下面我们就可以建立一个项目了,在“文件”菜单中选“新建”,再选“项目”,然后的选择见下图:

Image7

点击“确定”,然后选择保存目录。完成后按Ctrl+F10就行了。

如何使用“OpenWatcom C/C++ 1.0(0.85)”

2009年11月5日

说到OpenWatcom,我们不得不提一下Watcom。

Watcom系统编译器是加拿大Watcom公司开发的Intel x86体系16/32位编译器,其最新版是11.0c。

Watcom C/C++的集成开发环境极差,不像Borland C/C++和Visual C/C++那样有漂亮的界面,编译连结不过轻轻一点。Watcom C/C++的大部分使用者都在命令行下编译程序。想想吧!一个需要在命令行下编译程序的编译器,怎么匹敌Borland C/C++和Visual C/C++,甚至是C++ Builder呢?

当然,编译器的好坏并不能单单从使用方便使用上来比较,专业的程序员最关心的是目标程序的质量。Watcom系列编译器相比Borland编译器和Microsoft编译器有一个最大的优势,那便是速度:用Watcom C/C++编译出来的程序在速度上远远超越(记住,不是一点儿,是超越了许多)了Borland C/C++和Microsoft Visual C/C++编译出来的程序。这样一来,即使是没有集成开发环境,程序员们也认了。这也是不少游戏程序员亲昧于这个编译器的原因。

现在我们所用到的OpenWatcom C/C++ 1.0便是Watcom C/C++ 11.0c开放后的版本,它是免费、而且开放源码的。

一、下载与安装

在下载前,请选阅读它的授权协议。

官方网站

下载后直接解压到某个盘的根目录即可,推荐解压后目录为“C:\OpenWatcom”。

二、配置

由于OpenWatcom C/C++支持的平台相当多,所以针对不同的平台有不同的配置。主要在于系统变置的不同,这里主要讲一下针对32位DOS和Windows的配置:

32位DOS平台配置

WATCOM=C:\OpenWatcom
PATH=C:\OpenWatcom\Binw
INCLUDE=C:\OpenWatcom\H
LIBPATH=C:\OpenWatcom\LIB386
EDPATH=C:\OpenWatcom\EDDAT

●32位Windows配置

WATCOM=C:\OpenWatcom
PATH=C:\OpenWatcom\Binnt
INCLUDE=C:\OpenWatcom\H;C:\OpenWatcom\H\NT
LIBPATH=C:\OpenWatcom\LIB386;C:\OpenWatcom\LIB386\NT
EDPATH=C:\OpenWatcom\EDDAT

三、编译程序

OpenWatcom C/C++编译程序方法和Watcom C/C++ 11.0一致。

编译一个基于DOS/4GW的程序:wcl386 -l=dos4g hello.c

编译一个基于WindowsNT字符模式的程序:wcl386 -l=nt hello.c

编译一个基于WindowsNT窗口模式的程序:wcl386 -l=nt_win hello.c

编译一个基于Windows95的程序:wcl386 -l=win95 hello.c

如何使用“Borland C/C++ 5.5.1 for Win32”

2009年11月5日

“Borland C/C++ 5.5.1 for Win32”是Borland公司在2000年免费放出的一个C/C++编译器,其功能完整、包含多种SDK,且容量极小,安装版本大小仅8MB。 Borland公司现在的旗舰级产品“C++ Builder 5”内置的就是这一编译器,最新的“C++ Builder 6”内置的为“Borland C/C++ 5.6”。

它的免费仅适用于非盈利性软件的开发,以及教学使用。

由于没有集成开发环境,所以对某些开发者来说使用可能比较困难,在这里,我特地向这些开发者讲叙它的使用。

一、下载

下载地址

二、安装

运行安装程序,界面如下:

Image1

点击“下一步(N) >”按钮,出现以下界面:

Image2

在这一界面内选择安装路径,一般使用默认路径,点击“完成”完成安装。

三、建立配置文件

这里所说的配置文件是可建可不建的,但建议建立较好。

在C:\Borland\BCC55\bin目录内建立文本文件,并更名为bcc32.cfg,使用编辑工具打开这个文件,并输入以下内容:

-I”C:\Borland\BCC55\include”
-L”C:\Borland\BCC55\lib”

在同一目录内建立ilink32.cfg,并输入以下内容:

-L”C:\Borland\BCC55\lib”

四、使用

命令行下的程序编译可能大多数人不习惯,但也只能这样用。例如编译程序hello.cpp

BCC32 hello.cpp

FinalBurnAlpha中NEO-GEO游戏驱动程序的编写

2009年11月5日

作者:胡颖卓


二年前我写了《FinalBurn AlphaCPS-2游戏驱动程序的编写》一文,现由于模拟器界的三年原则惯例,所以很久都没有新的CPS-2游戏XOR表出现了。而现今由于SNK的复活,NEO-GEO游戏又慢慢的多了几个出来,所以我特地再为大家撰写这篇文章。

FinalBurn Alpha中,NEO-GEO驱动相比CPS-2驱动写起来较为简易,下面我以SNK PLAYMORE的大作《侍魂 零》为例,告诉各位如何编写它的驱动程序。

打开src\burn\neogeo\d_neogeo.cpp文件。

首先是书写游戏的ROM描述表:

static struct BurnRomInfo samsho5RomDesc[] =
{//    文件名        长度      CRC校验码   类型

{“270-p1.bin”, 0x800000, 0x611A6687, 0x10}, // 0 68K 代码

{“270-s1.bin”, 0x020000, 0x33227D62, 1},    // 1 文字层图片数据

{“270-c1.bin”, 0x800000, 0x4E7BDEA1, 1},    // 2 图片数据
{“270-c2.bin”, 0x800000, 0x7B444985, 1},    // 3
{“270-c3.bin”, 0x800000, 0x8C709A9B, 1},    // 4
{“270-c4.bin”, 0x800000, 0xCFD53F5C, 1},    // 5
{“270-c5.bin”, 0x800000, 0xC026D318, 1},    // 6
{“270-c6.bin”, 0x800000, 0xB3D9D204, 1},    // 7
{“270-c7.bin”, 0x800000, 0xFE03A025, 1},    // 8
{“270-c8.bin”, 0x800000, 0x89DB2D34, 1},    // 9

{“270-m1.bin”, 0x020000, 0x18114FB1, 0x10}, // 10 Z80 代码

{“270-v1.bin”, 0x400000, 0x6849136C, 2},    // 11 声音数据
{“270-v2.bin”, 0x400000, 0x222E1774, 2},    // 12
{“270-v3.bin”, 0x400000, 0xCD9E7ADC, 2},    // 13
{“270-v4.bin”, 0x400000, 0x8B305CAC, 2},    // 14

};

接下来是驱动的描述:

STDROMPICKEXT(samsho5, samsho5, neogeo);
STD_ROM_FN(samsho5);

struct BurnDriver BurnDrvSamSho5 =
{

{

“samsho5”,                //ROM文件名称
“Samurai Shodown V”,      //游戏名称
“”,                       //其它信息
“SNK Playmore”,           //游戏开发商
“Neo Geo”,                //游戏机型说明
“2003”,                   //游戏发行年代
NULL,                     //游戏主ROM名称
“neogeo”                  //游戏BIOS

},

BDF_GAME_WORKING,
2,                             //游戏人数
HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP | HARDWARE_SNK_SWAPC | HARDWARE_SNK_SRAM,
NULL,
samsho5RomInfo,                //ROM信息
samsho5RomName,                //ROM名称
neogeoInputInfo,
neogeoDIPInfo,
NeoInit,
NeoExit,
NeoFrame,
NeoRender,
NeoScan,
&NeoRecalcPalette,
nNeoScreenWidth,
224,
4,3

};

最后我们只需要在src\generated\driverlist.h中加入相应的项就可以了,祝大家玩的愉快!


鄂ICP备09027626号