digitalmars.D.learn - how to pass a ubyte[] to c interface?
- zhmt (3/3) Mar 12 2015 ubyte[] arr ;
- zhmt (21/21) Mar 12 2015 I have some source code of vibe.d, it does this in the same way,
- Rikki Cattermole (11/14) Mar 12 2015 Theoretically this should work.
- zhmt (2/18) Mar 12 2015 Thank you for your confirm,I will try again.
- Rikki Cattermole (5/28) Mar 12 2015 Just be careful about GC pointers. They could be free'd and the c
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/19) Mar 12 2015 Unless there is sentinel value at the end of the array, you must also
- zhmt (35/59) Mar 13 2015 sorry for "clang", I mean c , not clang of mac.
ubyte[] arr ; I pass the arr.ptr to c program, it fails silently. Is there any way to cast a ubyte[] to a clang pointer?
Mar 12 2015
I have some source code of vibe.d, it does this in the same way, and it works . void read(ubyte[] dst) { checkConnected(false); acquireReader(); scope(exit) releaseReader(); while (dst.length > 0) { checkConnected(false); logTrace("evbuffer_read %d bytes (fd %d)", dst.length, m_ctx.socketfd); auto nbytes = bufferevent_read(m_ctx.event, dst.ptr, dst.length); logTrace(" .. got %d bytes", nbytes); dst = dst[nbytes .. $]; if( dst.length == 0 ) break; checkConnected(false); m_ctx.core.yieldForEvent(); } logTrace("read data"); }
Mar 12 2015
On 13/03/2015 7:35 p.m., zhmt wrote:ubyte[] arr ; I pass the arr.ptr to c program, it fails silently. Is there any way to cast a ubyte[] to a clang pointer?Theoretically this should work. D: void func(ubyte[] value) { func(value.length, value.ptr); } extern(C) void func(size_t length, ubyte*); C: void func(size_t length, ubyte*) { // ... }
Mar 12 2015
On Friday, 13 March 2015 at 06:39:31 UTC, Rikki Cattermole wrote:On 13/03/2015 7:35 p.m., zhmt wrote:Thank you for your confirm,I will try again.ubyte[] arr ; I pass the arr.ptr to c program, it fails silently. Is there any way to cast a ubyte[] to a clang pointer?Theoretically this should work. D: void func(ubyte[] value) { func(value.length, value.ptr); } extern(C) void func(size_t length, ubyte*); C: void func(size_t length, ubyte*) { // ... }
Mar 12 2015
On 13/03/2015 7:47 p.m., zhmt wrote:On Friday, 13 March 2015 at 06:39:31 UTC, Rikki Cattermole wrote:Just be careful about GC pointers. They could be free'd and the c library thinks it is still live. Either keep a copy of the pointer alive on the heap somewhere or tell the GC to ignore it.On 13/03/2015 7:35 p.m., zhmt wrote:Thank you for your confirm,I will try again.ubyte[] arr ; I pass the arr.ptr to c program, it fails silently. Is there any way to cast a ubyte[] to a clang pointer?Theoretically this should work. D: void func(ubyte[] value) { func(value.length, value.ptr); } extern(C) void func(size_t length, ubyte*); C: void func(size_t length, ubyte*) { // ... }
Mar 12 2015
On 03/12/2015 11:35 PM, zhmt wrote:ubyte[] arr ; I pass the arr.ptr to c programUnless there is sentinel value at the end of the array, you must also pass the number of elements (as Rikki Cattermole has shown). However, if the C function holds on to that pointer for later use, you must also keep the array alive. You can ensure that by two general ways: a) The D-side slice must not be a local slice. For example, it can be a member of a long-living object or it is a module-scope variable. b) Tell the garbage collector that there is indeed a reference to that memory block somewhere else (even though there is no D-side reference to it). You can do this with GC.addRoot. (The opposite function is GC.removeRoot.), it fails silently.That's not good.Is there any way to cast a ubyte[] to a clang pointer?Going off-topic, I think you mean the C language when you say "clang", which may be confusing because there is also the compiler called clang. :) Ali
Mar 12 2015
On Friday, 13 March 2015 at 06:56:33 UTC, Ali Çehreli wrote:On 03/12/2015 11:35 PM, zhmt wrote:sorry for "clang", I mean c , not clang of mac. Thanks for you advice, I use coroutine, so the array will hold in stack, will not be gc before return. And I successfully passed the arr.ptr to c program. I found the root of problem: The order of method declaration in c++ class and d interface must be exactly the same: this is d code: interface CConn { void free(); int connect(ubyte* ip,int port,CFiberCtx fiberctx); int read(ubyte* buf,int offset, int len,CFiberCtx fiberctx); int readSome(ubyte* buf,int offset, int len,CFiberCtx fiberctx); int write(ubyte* buf,int offset, int len,CFiberCtx fiberctx); } this is c++ class: class CConn { public: //==== dlang interfaces; virtual void free(); virtual int connect(char* ip,int port,CFiberCtx *fiberctx); virtual int read(char* buf,int offset, int len,CFiberCtx *fiberctx); virtual int write(char* buf,int offset, int len,CFiberCtx *fiberctx); //ERROR : swap this line with below, everything will be ok virtual int readSome(char* buf,int offset, int len,CFiberCtx *fiberctx); } After swapping the last two lines, everything goes well. The tutorial of d dont mention this. Thanks for all replies.ubyte[] arr ; I pass the arr.ptr to c programUnless there is sentinel value at the end of the array, you must also pass the number of elements (as Rikki Cattermole has shown). However, if the C function holds on to that pointer for later use, you must also keep the array alive. You can ensure that by two general ways: a) The D-side slice must not be a local slice. For example, it can be a member of a long-living object or it is a module-scope variable. b) Tell the garbage collector that there is indeed a reference to that memory block somewhere else (even though there is no D-side reference to it). You can do this with GC.addRoot. (The opposite function is GC.removeRoot.), it fails silently.That's not good.Is there any way to cast a ubyte[] to a clang pointer?Going off-topic, I think you mean the C language when you say "clang", which may be confusing because there is also the compiler called clang. :) Ali
Mar 13 2015