www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to pass a ubyte[] to c interface?

reply "zhmt" <zhmtzhmt qq.com> writes:
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
next sibling parent "zhmt" <zhmtzhmt qq.com> writes:
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
prev sibling next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
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
parent reply "zhmt" <zhmtzhmt qq.com> writes:
On Friday, 13 March 2015 at 06:39:31 UTC, Rikki Cattermole wrote:
 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*) { // ... }
Thank you for your confirm,I will try again.
Mar 12 2015
parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 13/03/2015 7:47 p.m., zhmt wrote:
 On Friday, 13 March 2015 at 06:39:31 UTC, Rikki Cattermole wrote:
 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*) { // ... }
Thank you for your confirm,I will try again.
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.
Mar 12 2015
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/12/2015 11:35 PM, zhmt wrote:

 ubyte[] arr ;

 I pass the arr.ptr to c program
Unless 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
parent "zhmt" <zhmtzhmt qq.com> writes:
On Friday, 13 March 2015 at 06:56:33 UTC, Ali Çehreli wrote:
 On 03/12/2015 11:35 PM, zhmt wrote:

 ubyte[] arr ;

 I pass the arr.ptr to c program
Unless 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
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.
Mar 13 2015