I’m working on a project to create a VR sculpting tool voxel based, this project that involved two main process. On Unity I manage the user interaction and the storage of data structure. For the data manipulation I use c++ libraries. The voxel grid is very big, about 4000x4000 voxels, I need more efficiency, this is the reason why I chose to use the c++ dll. I have read more tutorial e docs about the intoroperability berween c# and c++, but I’m still confused about how to implement the comunication from two process. I have to manipulate two structure, one fixed size array of int (c#: int[] -> c++: int[])
and one variable size vector of pointer to a vector (c#: List<IntPtr> -> c++: std::vector<std::vector<int>*>)
.
Up till now, I’ve been able to read\write from the int[]
, I have some problem for the second one, I can’t add element to the vector from c++ dll, if I add an element from c# I don’t have problems to read and write it from c++.
The code of the two processes:
/************ C++ *************/
#define EXPORT_API __declspec(dllexport)
//Function to write into a int[] array
EXPORT_API bool GetIndices(int indices[], int indicesLenght) {
for(int i = 0; i < indicesLenght; i++){
indices *= 10;*
}
return true;
}
static void* blocksBufferHandle = NULL;
static void* blocksBufferHandleOriginal = NULL;
static int blocksBufferVertexCount;
static std::vector<int*> g_VertexSource;
EXPORT_API void SetBlocksBuffersFromUnity(void* blocksBufferHandleFromUnity, int blocksCount)
{
blocksBufferHandle = blocksBufferHandleFromUnity;
blocksBufferHandleOriginal = blocksBufferHandleFromUnity;
blocksBufferVertexCount = blocksCount;
g_VertexSource.resize(blocksCount);
for (int i = 0; i < blocksCount; ++i)
{
auto *b = new std::vector(16, 5);
g_VertexSource = b->data();
}
}
/************ C# *************/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using UnityEngine;
public class PluginImport : MonoBehaviour
{
[DllImport(“libUnityPlugin”, CallingConvention = CallingConvention.Cdecl)]
public static extern bool GetIndices([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] IntPtr indices, int indicesLength);
[DllImport(“__Internal”)]
private static extern void SetBlocksBuffersFromUnity(IntPtr blocks, int blockSize);
public int size; //Grid size
void Start() {
int indicesLenght = 10;
int[] indices = new int[indicesLenght];
GCHandle indicesHandle = GCHandle.Alloc(indices, GCHandleType.Pinned);
IntPtr addressIndices = indicesHandle.AddrOfPinnedObject();
GetIndices(addressIndices, indicesLenght);
Debug.Log("Indices value: " + (int)indices[0]); //Output: 10 OK
int blocksLength = 10;
var blocks = new List();
GCHandle blocksHandle = GCHandle.Alloc(blocks, GCHandleType.Pinned);
IntPtr addressBlocks = indicesHandle.AddrOfPinnedObject();
SetBlocksBuffersFromUnity(addressBlocks, blocksLength);
Debug.Log("Block value: " + blocks[o]); //Error
indicesHandle.Free();
blocksHandle.Free();
}
}
If I try to read the first element Unity of the vector, returns this error, If I print the length of blocks
is 0 :
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
I suppose c# doesn’t notice the addition of elements made by c++.
For some parts of the code (Setblocksbuffersfromunity) I took the cue from the Unity documentation.
I’m working on this code from about 2 month, I tried several solutions, but any worked for the vector.
Any suggestions?
thanks