发新话题
打印

转换C的.h文件为D模块

转换C的.h文件为D模块

知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070429

点击下面网址查看原文:
http://www.d-programming-language-china.org

by: uFramer D语言论坛 http://www.d-programming-language-china.org
from: http://www.digitalmars.com/d/htomodule.html
version: 基于DMD 1.014

尽管 D 不能直接编译 C 的源代码,但它可以同 C 代码很好的衔接,可以同 C 目标文件连接,还可以调用 DLL 中的 C 函数。C 代码的接口通常位于 C 的 .h 文件中。所以,同 C 代码衔接的关键就在于将 C .h 文件转换为 D 模块。事实证明,这个工作很难采用机械的方法完成,必须有人加以判断。下面就是执行这种转换的一些指导。

Preprocessor预处理器

.h files can sometimes be a bewildering morass of layers of macros, #include files, #ifdef's, etc. D doesn't include a text preprocessor like the C preprocessor, so the first step is to remove the need for it by taking the preprocessed output. For DMC (the Digital Mars C/C++ compiler), the command:

dmc -c program.h -e -l

will create a file program.lst which is the source file after all text preprocessing.
Remove all the #if, #ifdef, #include, etc. statements.

Linkage链接

通常,象下面这样将整个模块包起来:

extern (C)
{
     /*...文件内容...*/
}

会使代码采用 C 的链接风格。

Types型别

可以用简单的全局替换重命名C型别到D的型别。
下面是一个32位C代码的型别对应表。( 本文出处: http://www.d-programming-language-china.org )

Mapping C type to D type
C type D type
long double real
unsigned long long ulong
long long long
unsigned long uint
long int
unsigned uint
unsigned short ushort
signed char byte
unsigned char ubyte
wchar_t wchar or dchar
bool bool, byte, int
size_t size_t
ptrdiff_t ptrdiff_t

NULL

应该使用 NULL 宏或者 ((void*)0) 来代替 null 。

Numeric Literals数值文字量

删除所有'L'或'l'数值文字量后缀,通常C的long对应于D的int.'LL'后缀应该用'L'来代替。所有'u'后缀不用改。

String Literals字符串文字量

在多数情况下可以直接移除'L'前缀,需要时D会隐式转换到宽字符。当然也可以这样替换:

L"string"

替换成:

"string"w    // for 16 bit wide characters
"string"d    // for 32 bit wide characters

Macros宏

象这样的宏:( 本文出处: http://www.d-programming-language-china.org )

#define FOO    1
#define BAR    2
#define ABC    3
#define DEF    40

可以被替换成:

enum
{    FOO = 1,
    BAR = 2,
    ABC = 3,
    DEF = 40
}

或者:

const int FOO = 1;
const int BAR = 2;
const int ABC = 3;
const int DEF = 40;

象这样函数风格的宏:

#define MAX(a,b) ((a) < (b) ? (b) : (a))

可以被替换成:

int MAX(int a, int b) { return (a < b) ? b : a; }

The functions, however, won't work if they appear inside static initializers that must be evaluated at compile time rather than runtime. To do it at compile time, a template can be used:( 本文出处: http://www.d-programming-language-china.org )

#define GT_DEPTH_SHIFT    (0)
#define GT_SIZE_SHIFT    (8)
#define GT_SCHEME_SHIFT (24)
#define GT_DEPTH_MASK    (0xffU << GT_DEPTH_SHIFT)
#define GT_TEXT    ((0x01) << GT_SCHEME_SHIFT)

/* Macro that constructs a graphtype */
#define GT_CONSTRUCT(depth,scheme,size) \
    ((depth) | (scheme) | ((size) << GT_SIZE_SHIFT))

/* Common graphtypes */
#define GT_TEXT16    GT_CONSTRUCT(4, GT_TEXT, 16)

对应的D版本是这样的:

const uint GT_DEPTH_SHIFT    = 0;
const uint GT_SIZE_SHIFT    = 8;
const uint GT_SCHEME_SHIFT = 24;
const uint GT_DEPTH_MASK    = 0xffU << GT_DEPTH_SHIFT;
const uint GT_TEXT    = 0x01 << GT_SCHEME_SHIFT;

// Template that constructs a graphtype
template GT_CONSTRUCT(uint depth, uint scheme, uint size)
{
 // notice the name of the const is the same as that of the template
 const uint GT_CONSTRUCT = (depth | scheme | (size << GT_SIZE_SHIFT));
}

// Common graphtypes
const uint GT_TEXT16 = GT_CONSTRUCT!(4, GT_TEXT, 16);

Declaration Lists声明列表

D只允许同类型的声明列表,因此:( 本文出处: http://www.d-programming-language-china.org )

int *p, q, t[3], *s;

应该写成这样:

int* p, s;
int q;
int[3] t;

Void Parameter Lists空参数列表

空参数的函数:

int foo(void);

在D里这样写:( 本文出处: http://www.d-programming-language-china.org )

int foo();

Const Type Modifiers

Const 类型修饰符

D has const as a storage class, not a type modifier. Hence, just drop any const used as a type modifier:

void foo(const int *p, char *const q);
void foo(int* p, char* q);

Extern Global C Variables外部全局C变量

D里声明一个变量,也就是定义了一个变量。如果也在链接进来的C object文件里定义了,就是一个多次定义错误。要解决这个问题,可以使用外部存储类。例如有一个C头文件foo.h:

struct Foo { };
struct Foo bar;

可以用D模块foo.d来代替:

struct Foo { }
extern (C)
{
    extern Foo bar;
}

Typedef

在 D 中 alias 等价于 C 中的 typedef :( 本文出处: http://www.d-programming-language-china.org )

typedef int foo;

变为:

alias int foo;

Structs结构

C的结构:

typedef struct Foo
{    int a;
    int b;
} Foo, *pFoo, *lpFoo;

替换成:

struct Foo
{    int a;
    int b;
}
alias Foo* pFoo, lpFoo;

Struct Member Alignment结构成员对齐

A good D implementation by default will align struct members the same way as the C compiler it was designed to work with. But if the .h file has some #pragma's to control alignment, they can be duplicated with the D align attribute:

#pragma pack(1)
struct Foo
{
    int a;
    int b;
};
#pragma pack()

becomes:

struct Foo
{
    align (1):
    int a;
    int b;
}

Nested Structs嵌套结构

struct Foo
{
    int a;
    struct Bar
    {
    int c;
    } bar;
};

struct Abc
{
    int a;
    struct
    {
    int c;
    } bar;
};

改成D是这样的:

struct Foo
{
    int a;
    struct Bar
    {
    int c;
    }
    Bar bar;
}

struct Abc
{
    int a;
    struct
    {
    int c;
    }
}

__cdecl, __pascal, __stdcall

int __cdecl x;
int __cdecl foo(int a);
int __pascal bar(int b);
int __stdcall abc(int c);

转换成:

    extern (C) int x;
    extern (C) int foo(int a);
    extern (Pascal) int bar(int b);
    extern (Windows) int abc(int c);

__declspec(dllimport)

__declspec(dllimport) int __stdcall foo(int a);

转换成:

export extern (Windows) int foo(int a);

__fastcall

Unfortunately, D doesn't support the __fastcall convention. Therefore, a shim will be needed, either written in C:

int __fastcall foo(int a);

int myfoo(int a)
{
    return foo(int a);
}

and compiled with a C compiler that supports __fastcall and linked in, or compile the above, disassemble it with obj2asm and insert it in a D myfoo shim with inline assembler.
http://www.digitalmars.com/ctg/obj2asm.html
http://digitalmars.com/d/iasm.html( 本文出处: http://www.d-programming-language-china.org )

( lastupdate:20070429 最新文章请访问http://www.d-programming-language-china.org )

关于一大步成功社区:
yidabu提倡在交流中学习,在分享中提高
收集感兴趣的知识,写下心得,通过网络与别人一起分享
理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的
网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台

TOP

发新话题