Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
March 13, 2015 how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
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? |
March 13, 2015 Re: how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
Posted in reply to zhmt | 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"); } |
March 13, 2015 Re: how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
Posted in reply to zhmt | 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*) {
// ...
}
|
March 13, 2015 Re: how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rikki Cattermole | 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.
|
March 13, 2015 Re: how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
Posted in reply to zhmt | 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.
|
March 13, 2015 Re: how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
Posted in reply to zhmt | 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 |
March 13, 2015 Re: how to pass a ubyte[] to c interface? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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.
|
Copyright © 1999-2021 by the D Language Foundation