C到D:结构作为类型并初始化?
我有这些C宏,希望将它们转换为纯D(与原始C文件的接口相同) 这是我当前的实现:C到D:结构作为类型并初始化?,d,ctod,D,Ctod,我有这些C宏,希望将它们转换为纯D(与原始C文件的接口相同) 这是我当前的实现: import std.stdio; import core.stdc.config; import core.stdc.stdlib; struct __kstream_t(type_t) { ubyte *buf; int begin, end, is_eof; type_t f; } mixin template __KS_BASIC(type_t, ubyte __bufsiz
import std.stdio;
import core.stdc.config;
import core.stdc.stdlib;
struct __kstream_t(type_t) {
ubyte *buf;
int begin, end, is_eof;
type_t f;
}
mixin template __KS_BASIC(type_t, ubyte __bufsize){
// mixin(__KS_TYPE!type_t);
alias kstream_t = __kstream_t!type_t;
static kstream_t *ks_init(type_t f)
{
kstream_t *ks = cast(kstream_t*)calloc(1, kstream_t.sizeof);
ks.f = f;
ks.buf = cast(ubyte*)malloc(__bufsize);
return ks;
}
static void ks_destroy(kstream_t *ks)
{
if (ks) {
free(ks.buf);
free(ks);
writeln("Destroyed struct.");
}
}
}
void main(){
mixin __KS_BASIC!(int, 12);
auto ks = ks_init( 14);
ks.buf[0] = 125;
writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]);
ks_destroy(ks);
}
当前的D版本运行良好,但是我可以对代码进行任何调整和修剪吗?它看起来仍然很保守。例如,kh_init
可以是这样的:
static kstream_t *ks_init(type_t f){
kstream_t* ks;
ks.f = f;
return ks;
}
但是这个版本给出了一个精液错误
此外,在
ks_init
和ks_destroy
中手动处理内存是否有任何好处?它会出错,因为您没有在堆栈上分配kstream\u t
,而是分配一个初始化为null
的指针。
要在堆栈上分配它,您需要执行以下操作:
但是当您尝试访问它的任何字段时,这仍然会在main()
中出错,因为只要作用域退出,堆栈分配就会被释放,这在本例中是ks_init()
您应该在gc上分配它:
编辑:对不起,我没有谈到缓冲区的分配,您可以将maclloc的内存分配给GC,以便他可以为您管理它
但是,你似乎有兴趣把代码移植到惯用的D。然后有一些事情要考虑,你已经找出其中的大部分:
然而,我们不能总是避免GC/堆分配,如果数组很大,我们必须使用新的。
当前在D中实现垃圾收集器的速度很慢(我们正在摆脱它,很快就不再使用GC),虽然它不会那么慢,但大多数时候你并不需要额外的速度,所以你不需要体验使用
new
这是一个更D的版本,来自@DejanLekic的评论和@Sahmi的回答。我发布了一个答案,因为我不想改变原来的问题
import std.stdio;
import core.stdc.config;
import core.stdc.stdlib;
struct __kstream_t(type_t) {
ubyte *buf;
int begin, end, is_eof;
type_t f;
this(type_t f, ubyte bs){
this.f = f;
this.buf = cast(ubyte* )malloc(bs);//Can this be avoided or more D?
}
}
mixin template __KS_BASIC(type_t, ubyte __bufsize){
alias kstream_t = __kstream_t!type_t;
static kstream_t* ks_init(type_t f){
auto ks = new kstream_t(f, __bufsize);
return ks;
}
static void ks_destroy(kstream_t *ks)
{
if (ks) {
destroy(ks);
writeln("Destroyed struct.");
}
}
}
void main(){
mixin __KS_BASIC!(int, 12);
auto ks = ks_init( 14);
ks.buf[0] = 125;
writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]);
ks_destroy(ks);
}
这个问题应该迁移到ks_init(),因为您需要分配稍后在
ks.f=f代码>行。您需要调用malloc()、calloc()或(D方式)您应该能够简单地做到这一点:kstream\u t*ks=new kstream\u t代码>@RobertH:复活节让我离开了一段时间。我的回答是:我现在的“工作”D版本还没有经过测试。我还没有到优化步骤。我有兴趣有一个工作和真正的D版本。此外,有人告诉我,SO的D程序员比SO的其他兄弟姐妹都多。所以我想在这里发帖。@DejanLekic应用了你的建议,但还是得到了seg。错误。如果你得到了分段错误,那一定是我们在这里看不到的一些代码,因为上面的代码在我的工作站上不会产生分段错误……这是@DejanLekic发布的相同想法的一个更完美的答案。但是,我尝试了,但仍然出现了分段错误。我怀疑我必须用显式构造函数编写\ukstream\ut
结构。但我仍然不知道如何去做,事实上,你们正朝着正确的方向前进。我在上面编辑了我的答案。希望能有帮助。是的,我想要一个惯用的D代码,如果它不会显著影响性能的话。目前,性能还不是首要任务。所以都是白痴。哦,错过了“ma”。只是好奇,我们能否避免在构造函数中使用新的ubyte[bs]
,从而使它与@nogc
兼容。仅供参考,我不太了解“@nogc”,也不知道为什么避免GC实际上更好。但这似乎与性能有关。和以前一样。。。如果您同意由D的GC分配的结构,则可以避免malloc()。
kstream_t ks; // still bad
auto ks = new kstream_t;
ks.buf = cast(ubyte*)malloc(__bufsize);
import core.memory : GC;
GC.addRange(ks.buf, __bufsize);
import std.stdio;
struct Kstream(T) {
ubyte[] buf;
int begin, end, is_eof;
T f;
this(T f, ubyte bs)
{
this.f = f;
this.buf = new ubyte[bs];
}
~this()
{
writeln("Destroyed struct.");
}
}
void main(){
auto ks = Kstream!int(14, 12);
ks.buf[0] = 125;
writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]);
}
import std.stdio;
struct Kstream(T, size_t N) {
ubyte[N] buf;
int begin, end, is_eof;
T f;
this(T f)
{
this.f = f;
}
~this()
{
// we cannot call writeln in @nogc code
//writeln("Destroyed struct.");
}
}
@nogc
void main(){
auto ks = Kstream!(int, 12)(14);
ks.buf[0] = 125;
// we cannot call writeln in @nogc code
//writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]);
}
import std.stdio;
import core.stdc.config;
import core.stdc.stdlib;
struct __kstream_t(type_t) {
ubyte *buf;
int begin, end, is_eof;
type_t f;
this(type_t f, ubyte bs){
this.f = f;
this.buf = cast(ubyte* )malloc(bs);//Can this be avoided or more D?
}
}
mixin template __KS_BASIC(type_t, ubyte __bufsize){
alias kstream_t = __kstream_t!type_t;
static kstream_t* ks_init(type_t f){
auto ks = new kstream_t(f, __bufsize);
return ks;
}
static void ks_destroy(kstream_t *ks)
{
if (ks) {
destroy(ks);
writeln("Destroyed struct.");
}
}
}
void main(){
mixin __KS_BASIC!(int, 12);
auto ks = ks_init( 14);
ks.buf[0] = 125;
writeln("ks.f: ", ks.f, ", buf: ", ks.buf[0]);
ks_destroy(ks);
}