www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - D array to void* and back

reply "ref2401" <refactor24 gmail.com> writes:
Hello everyone,

I pass a D array as void* into a function.

When I'm trying to cast a void* parameter to a D array I get 
'Access Violation' error.
However if I define ArrayLike struct which looks like D array 
then casting will succeed.
What should I do? Should I stick to ArrayLike wrapper and just 
live? :)

struct ArrayLike(T) {
	this(T[] arr) {
		ptr = arr.ptr;
		length = arr.length;
	}

	T* ptr;
	size_t length;

	T[] asArray() {
		return ptr[0 .. length];
	}
}

void funcLibC_Array(void* data) {
	int[] arr = *cast(int[]*)data;
	writeln("funcLibC_Array: ", arr);
}

void funcLibC_ArrayLike(void* data) {
	ArrayLike!int arrLike = *cast(ArrayLike!int*)data;
	writeln("funcLibC_ArrayLike: ", arrLike.asArray());
}

void main(string[] args) {
	int[] arr = [1, 2, 3];
	auto arrLike = ArrayLike!int(arr);


	funcLibC_ArrayLike(&arrLike);
	funcLibC_Array(arr.ptr); // 'Access Violation error' is thrown 
here.
}
Aug 03 2015
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/03/2015 02:23 PM, ref2401 wrote:

 void funcLibC_Array(void* data) {
      int[] arr = *cast(int[]*)data;
You are still in D, so int[] has a different meaning from a C array. (D's arrays are array-like. ;) ) Since arr.ptr is the pointer to the first element, and since that is exactly how C functions access array elements, do this: import std.stdio; void funcLibC_Array(void* data) { int* arr = cast(int*)data; writeln("funcLibC_Array: ", arr); foreach (i; 0 .. 3) { writeln(arr[i]); } } void main(string[] args) { int[] arr = [1, 2, 3]; funcLibC_Array(arr.ptr); // 'Access Violation error' is thrown here. } But you still need to communicate how many elements there are in the array. (I used literal 3). Ali
Aug 03 2015
parent reply "ref2401" <refactor24 gmail.com> writes:
On Monday, 3 August 2015 at 21:28:29 UTC, Ali Çehreli wrote:

 But you still need to communicate how many elements there are 
 in the array. (I used literal 3).
Yes I do. I hope there is a neat way to pass array's length too.
Aug 03 2015
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/03/2015 02:33 PM, ref2401 wrote:
 On Monday, 3 August 2015 at 21:28:29 UTC, Ali Çehreli wrote:

 But you still need to communicate how many elements there are in the
 array. (I used literal 3).
Yes I do. I hope there is a neat way to pass array's length too.
Not possible in C. :( Common methods: * An array-like struct * A separate parameter for the number of elements * A sentinel value at the end of the array (e.g. '\0' for strings or NULL for arrays of pointers to objects, -1 where it is not valid as an element value, etc.) Ali
Aug 03 2015
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/3/15 5:23 PM, ref2401 wrote:
 Hello everyone,

 I pass a D array as void* into a function.

 When I'm trying to cast a void* parameter to a D array I get 'Access
 Violation' error.
 However if I define ArrayLike struct which looks like D array then
 casting will succeed.
 What should I do? Should I stick to ArrayLike wrapper and just live? :)

 struct ArrayLike(T) {
      this(T[] arr) {
          ptr = arr.ptr;
          length = arr.length;
      }

      T* ptr;
      size_t length;
In T[], length is stored first, then pointer. This is likely where you are getting hung up. You didn't post your C code, so I don't know exactly what you are expecting on the other side.
      T[] asArray() {
          return ptr[0 .. length];
      }
 }

 void funcLibC_Array(void* data) {
      int[] arr = *cast(int[]*)data;
      writeln("funcLibC_Array: ", arr);
 }

 void funcLibC_ArrayLike(void* data) {
      ArrayLike!int arrLike = *cast(ArrayLike!int*)data;
      writeln("funcLibC_ArrayLike: ", arrLike.asArray());
 }

 void main(string[] args) {
      int[] arr = [1, 2, 3];
      auto arrLike = ArrayLike!int(arr);


      funcLibC_ArrayLike(&arrLike);
      funcLibC_Array(arr.ptr); // 'Access Violation error' is thrown here.
This is wrong, arr.ptr is just the pointer to the DATA, not a pointer to an array struct (which contains pointer and length). You want to do funcLibC_Array(&arr); Posting your C code (at least the part that reestablishes the type from a void*) may give more clarity to what you are trying to do. -Steve
Aug 03 2015