I have a function in a native dll whose function looks like this
int GetActiveNames(char* names[]);
How do I create my PInvoke wrapper method in C# to the above function which returns me an array of strings/characters?
To be more descriptive..
I tried the P/Invoke way and its showing the following error Attempted to read or write protected memory. This is often an indication that other memory is corrupt..
I just stripped down the actual C function signature to make it simple. But here is the complete C function signature and the description of the parameters of the function
int OpalGetActiveProjects(unsigned short allocatedProjects,
unsigned short *numProjects,
unsigned short allocatedModels,
unsigned short *numModels,
unsigned short allocatedProjectsPathLen,
unsigned short *maxProjectPathLen,
unsigned short allocatedModelPathLen,
unsigned short *maxModelPathLen,
unsigned short allocatedMachineNameLen,
unsigned short *maxMachineNameLen,
unsigned short allocatedIpLen,
unsigned short *maxIpLen,
char *projectPaths[],
unsigned short instanceIDs[],
char *machineNames[],
char *controllerIPs[],
char *modelPaths[],
unsigned short numModelsPerProject[]
unsigned short modelIDs[],
unsigned short modelStates[]);
The function returns a list of active projects. For each project, this function returns the full path of the configuration file, the name and the IP address of the machine that opened this project, the instance ID of the current project session, and the list of models belonging to this project. For each model, path, ID and state are returned.If the allocated storage is too small for any of the arguments, none of the lists are returned, but the numProjects, numModels, maxProjectPathLen, maxModelPathLen, maxMachineNameLen and maxIpLen values are set, and the return value is E2BIG. An application can use this fact to specify lengths of 0 on a first call, allocate the required storage and issue a second call to get the information.
Input parameters
allocatedProjects: number of projects for which storage was allocated by the caller for the paths, machine name, IP addresses and instance ids. allocatedModels: number of models for which storage was allocated by the caller for the names, paths and instance ids. allocatedProjectPathLen: allocated length of storage to receive the project paths allocatedModelPathLen: allocated length of storage to receive the model paths allocatedMachineNameLen: allocated length of storage to receive the machine names allocatedIpLen: allocated length of storage to receive the IP addresses
Output parameters
numProjects: pointer to where the API will store the actual number of active projects. numModels: pointer to where the API will store the actual total number of models for all active projects. maxProjectPathLen: pointer to where the API will store the length of the longest project path. maxModelPathLen: pointer to where the API will store the length of the longest model path. maxMachineNameLen: pointer to where the API will store the length of the longest machine name. maxIpLen: pointer to where the API will store the length of the longest IP address. projectPaths: array of strings where the API will store the paths of the active projects’ configuration files. instanceIDs: array where the API will store the instance Ids of the active projects. machineNames: array where the API will store the machine names. controllerIPs: array where the API will store the IP adresses. modelPaths: array where the API will store the model paths of all active projects. numModelsPerProject: array where the API will store the number of models for each project. Use these values to determine what model belongs to what project. modelIDs: array where the API will store the model IDs for all active projects. modelStates: array where the API will store the model states for all active projects.
There is also a C program which uses the OpalGetActiveProjects() function to get the projectPaths, machineNames, etc..
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
// Header for getcwd() is platform-dependent
#if defined(WIN32)
#include <direct.h>
#include <windows.h>
#elif defined(__linux__)
#include <unistd.h>
#define _MAX_PATH 256
#endif
#include "OpalApi.h"
void PrintError(int rc, char *funcName);
#define FALSE 0
#define TRUE 1
int main (int argc, char* argv[])
{
char **projectPath, **modelPath;
char *projectPaths, *modelPaths;
char **loaderMachineName, **controllerIp;
char *loaderMachineNames, *controllerIps;
int i, rc, projectIdx;
unsigned short *instId;
int *instId2;
int * modelIds;
unsigned short *numModelsPerProject;
unsigned short *modelId;
unsigned short *modelState;
unsigned short allocProjects, numProjects;
unsigned short allocModels, numModels;
unsigned short allocProjectPathLen, maxProjectPathLen;
unsigned short allocModelPathLen, maxModelPathLen;
unsigned short allocMachineLen, maxMachineLen;
unsigned short allocIpLen, maxIpLen;
// Obtenir la taille des données.
allocProjects =allocModels = 0;
allocProjectPathLen = allocModelPathLen = 0;
allocMachineLen = allocIpLen = 0;
rc = OpalGetActiveProjects( 0, &allocProjects,
0, &allocModels,
0, &allocProjectPathLen,
0, &allocModelPathLen,
0, &allocMachineLen,
0, &allocIpLen,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL );
if ((rc != 0) && (rc != E2BIG))
{
PrintError(rc, "OpalGetActiveProject");
printf(" - alGetActiveProjects error output !!!\n");
printf("\t numProjects - %i \n", allocProjects);
printf("\t numModels - %i \n", allocModels);
printf("\t maxProjectPathLen - %i \n", allocProjectPathLen);
printf("\t maxModelPathLen - %i \n", allocModelPathLen);
//printf("\t maxMachineNameLen - %i \n", maxMachineNameLen);
printf("\t maxIpLen - %i \n", allocIpLen);
return (rc);
// Erreur
//return returnInstance;
}
projectPath = (char **)_alloca(allocProjects * sizeof(*projectPath));
projectPaths = (char *)_alloca(allocProjects * (allocProjectPathLen + 1) * sizeof(*projectPaths));
loaderMachineName = (char **)_alloca(allocProjects * sizeof(*loaderMachineName));
loaderMachineNames = (char *)_alloca(allocProjects * (allocMachineLen + 1) * sizeof(*loaderMachineNames));
controllerIp = (char **)_alloca(allocProjects * sizeof(*controllerIp));
controllerIps = (char *)_alloca(allocProjects * (allocIpLen + 1) * sizeof(*controllerIps));
numModelsPerProject = (unsigned short*)_alloca(allocProjects * sizeof(*numModelsPerProject));
modelPath = (char **)_alloca(allocModels * sizeof(*modelPath));
modelPaths = (char *)_alloca(allocModels * (allocModelPathLen + 1) * sizeof(*modelPaths));
for (i = 0; i < allocProjects; ++i)
{
projectPath[i] = &projectPaths[i * (allocProjectPathLen + 1)];
loaderMachineName[i] = &loaderMachineNames[i * (allocMachineLen + 1)];
controllerIp[i] = &controllerIps[i * (allocIpLen + 1)];
}
for (i = 0; i < allocModels; ++i)
{
modelPath[i] = &modelPaths[i * (allocModelPathLen + 1)];
}
instId = (unsigned short *)_alloca(allocProjects * sizeof(*instId));
instId2 = (int *)_alloca(allocProjects * sizeof(*instId2));
modelId = (unsigned short*)_alloca(allocModels * sizeof(*modelId));
modelState = (unsigned short *)_alloca(allocModels * sizeof(*modelState));
rc = OpalGetActiveProjects( allocProjects, &numProjects,
allocModels, &numModels,
allocProjectPathLen, &maxProjectPathLen,
allocModelPathLen, &maxModelPathLen,
allocMachineLen, &maxMachineLen,
allocIpLen, &maxIpLen,
projectPath, instId,
loaderMachineName, controllerIp, modelPath,
numModelsPerProject, modelId, modelState);
printf(" - OpalGetActiveProjects output !!!\n");
printf("\t numProjects - %i \n", allocProjects);
printf("\t numModels - %i \n", allocModels);
printf("\t maxProjectPathLen - %i \n", allocProjectPathLen);
printf("\t maxModelPathLen - %i \n", allocModelPathLen);
//printf("\t maxMachineNameLen - %i \n", maxMachineNameLen);
printf("\t maxIpLen - %i \n", allocIpLen);
for(i=0; i<numProjects; i++)
{
printf("\t \t projectPath[%d] = %s \n", i, *(projectPath +i));
printf("\t \t instId[%d] = %d \n", i, *(instId + i));
printf("\t \t loaderMachineName[%d] = %s \n", i, *(loaderMachineName + i));
printf("\t \t controllerIp[%d] = %s \n", i, *(controllerIp + i));
printf("\t \t numModelsPerProject[%d] = %d \n", i, * (numModelsPerProject +i));
}
for(i=0; i<numModels; i++)
{
printf("\t \t modelPath[%d] = %s \n", i, *(modelPath+i));
printf("\t \t modelId[%d] = %d \n", i, *(modelId +i));
printf("\t \t modelState[%d] = %d \n", i, *(modelState+i));
}
OpalDisconnect();
getchar();
}
void PrintError(int rc, char *funcName)
{
char buf[512];
unsigned short len;
OpalGetLastErrMsg(buf, sizeof(buf), &len);
printf("Error !!! \n %s (code %d) from %s\n", buf, rc, funcName);
}