I would like to call this C++ function from my C# code:
void GetArrayOfNames(char** names, int nbOfNames);
To call it in C++, I just define an array of char*:
char* aNames[20];
And allocate each name in a loop:
for(int i-0; i<20; i++)
{
aNames[i] = new char[50];
}
Then call:
GetArrayOfNames(aNames, 20);
In my C# code, I have:
[DllImport("MyDLL.dll")]
unsafe static extern void GetArrayOfNames(char** ppNames, int nbOfNames);
Now, how do I do the memory allocation and call GetArrayOfNames? Also, any way of not having to declare my function as "unsafe"?
Probably:
static extern void GetArrayOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr] StringBuilder[] args, int count);
// Call using
StringBuilder[] arr = new StringBuilder[20];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = new StringBuilder(50);
}
GetArrayOfNames(arr, arr.Length);
As I understand char**
is just a reference to string. I created a small test for myself and it worked fine:
class Program
{
[DllImport("TestCppLib.dll", CharSet = CharSet.Ansi, EntryPoint = "?fnTestCppLib@@YAHPAPAD@Z", CallingConvention=CallingConvention.Cdecl)]
extern static int fnTestCppLib(ref string s);
static void Main(string[] args)
{
var s = "some";
var t = fnTestCppLib(ref s);
Debug.Assert(s == "test");
}
}
The implementation of function in C++ is:
TESTCPPLIB_API int fnTestCppLib(char ** str)
{
*str = "test";
return 42;
}
This ended up working:
static extern int GetArrayOfNames(IntPtr[] astr, int iLength);
And called/setup like this:
IntPtr[] intArr = new IntPtr[200];
for (int i = 0; i < intArr.Length; i++)
{
intArr[i] = Marshal.AllocHGlobal(256);
}
int nbOfNames = 2;
GetArrayOfNames(intArr, nbOfNames);
And to put back in a string:
string tmp;
tmp = Marshal.PtrToStringAnsi(intArr[i]);
Can i help you? my sample code in C++:
//CamMethods.cpp:
#include <iostream>
using namespace std;
#include "CamPS.h"
namespace Export {
char * CameraPS::CamStart(char *s){
return "teste";
};
}
//CamPs.h
namespace Export{
class CameraPS
{
public:
_declspec(dllexport) char * _stdcall CamStart(char *s);
};
}
and in C# i call:
using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;
public class DllTeste : MonoBehaviour
{
public int x;
[DllImport ("PS_Cam.dll", EntryPoint="CamStart", CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr CamStart (int s);//i can put <string> in same place of <int>
void Start ()
{
}
void Update ()
{
// IntPtr a = CamStart(x);
// string b = Marshal.PtrToStringAnsi(a);
// Debug.Log(b);
Debug.Log(Marshal.PtrToStringAnsi(CamStart(x)));
}
}
Sorry for my english.