> 文章列表 > d修复导入c的问题

d修复导入c的问题

d修复导入c的问题

原文

void my_fatal()
{*((volatile unsigned int *) 0) = (unsigned int) 0xdeadbeefUL;
}

导入C中忽略易失.
可这样替代:

static void* p;
*(unsigned int*)p = (unsigned int) 0xdeadbeefUL;

导入C赋值数组复合字面给使用GC分配的指针

void fn()
{void *p = (int[1]){0};
}

这使用_d_arrayliteralTX()数组分配存储
此外,用-betterC时,因为"TypeInfo不能与-betterC一起使用",而无法编译
其他编译器中,字面有"auto"存储持续时间,因此它与使用局部变量相同.
此测试检测是否是用GC分配指针:

int test()
{void *prev;for (int i = 0; i < 2; i++){void *curr = (int[1]){0};//在两个`循环`迭代中应有相同地址if (i == 0)prev = curr;elseif (curr != prev) return 1;}return 0;
}
_Static_assert(test() == 0, "");
int main()
{return test();
}

已修复.

导入C的属性候选,2
不能取字面地址:这里

void fn()
{int *a = &(int[1]){0};int *b = &(int){0};
}

第一行编译成功了,第二行不行.

CTFE中使用复合字面数组指针会导致"无效指针的解引用",这里

int fn()
{int *p = (int[1]){0};*p = 0;return *p;
}
_Static_assert(fn() == 0, "");
int main()
{return fn();
}

CTFE外工作.
虽然可使它工作,但它是无效的C11代码.
现在在ctfeexpr.d(578)上给出断定错误.

如下不编译

union nk_page_data *pd = (union nk_page_data*)((void*)((char*)(1 ? (tbl): &((union nk_page_data*)0)->tbl) - (__builtin_offsetof(nk_page_data,tbl))));

这是化简版:

#define NK_OFFSETOF(st,m) (__builtin_offsetof(st,m))
#define NK_ALIGNOF(t) NK_OFFSETOF(struct {char c; t _h;}, _h)struct nk_command{};void test()
{const int align = NK_ALIGNOF(struct nk_command);
}
// 用cpp -P -Evoid test()
{const int align = (__builtin_offsetof(struct {char c; struct nk_command _h;},_h));
}

GCC编译,但导入C不编译.
现在编译了.
交叉编译
交叉编译时,经常要用不同预处理器来获得正确的平台定义.在此不用CC环境变量,也没有开关.
当然,dmd不会做太多的交叉编译,但如果可完成,那就太好了.

dmd交叉编译使用了-os=windows,-os=freebsd等开关,我一直都在用它.
但你是对的,交叉编译.c文件有个问题,你如何在另一个平台上运行C预处理器?

导入C名字冲突

假设a.c包含#include<stdio.h>,b.c也包含它.
然后D文件同时导入a和b.现在像printf此函数会出现名字冲突.
这在D中是正常的,因为不同模块有自己的名字空间.但是在C中,不同头文件包含不同的东西是很常见的.一个导入保护可保持它在那里,但是在D中这并不管用.
我建议放importC符号在神奇模块中,然后别名它们公开/选择性地导入到使用包含导入的D模块中.然后引用相同的C名字空间,同时保持D名字空间的卫生性并避免虚假冲突.

无法编译示例

import std.stdio;
import square;
void main()
{int i = 7;writefln("%s的平方为%s", i, square.square(i));
}

示例
刚试过了,它工作正常,因为已重命名square.cfunctions.c

编译问题
我在ManjaroLinux上尝试用DMD2.101.1编译Nuklear库时,不小心碰到了同样的八哥.
根据assert.h错误消息和源代码,我认为ImportC试图使用以下assert的定义:

#  define assert(expr)                            \\((void) sizeof ((expr) ? 1 : 0), __extension__ ({            \\if(expr) \\; /* empty */\\else                                \\__assert_fail(#expr,__FILE__,__LINE__,__ASSERT_FUNCTION);\\
}))

语句
GCC把:

{语句; 语句;}

当作表达式.
__PRETTY_FUNCTION___ASSERT_FUNCTION宏中隐藏.
可通过转换语句表达式为不带参数的嵌套函数来支持语句表达式.
但是,带跳进跳出语句表达式时,会不起作用.