【发布时间】:2012-09-19 12:22:34
【问题描述】:
我在本机 dll 中有一个函数,其函数如下所示
int GetActiveNames(char* names[]);
如何在 C# 中为返回字符串/字符数组的上述函数创建我的 PInvoke 包装器方法?
为了更具描述性..
我尝试了 P/Invoke 方式并显示以下错误 尝试读取或写入受保护的内存。这通常表明其他内存已损坏。。
我只是剥离了实际的 C 函数签名以使其简单。但是这里是完整的C函数签名和函数参数的描述
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[]);
该函数返回活动项目的列表。对于每个项目,此函数返回配置文件的完整路径、打开该项目的机器的名称和 IP 地址、当前项目会话的实例 ID 以及属于该项目的模型列表。 对于每个模型,返回路径、ID 和状态。如果分配的存储对于任何参数来说太小,则不返回任何列表,但会设置 numProjects、numModels、maxProjectPathLen、maxModelPathLen、maxMachineNameLen 和 maxIpLen 值,并且返回值为 E2BIG。应用程序可以使用此事实在第一次调用时将长度指定为 0,分配所需的存储空间并发出第二次调用以获取信息。
输入参数
allocatedProjects:分配存储空间的项目数 路径、机器名、IP 地址的调用者 和实例 ID。 allocatedModels:分配存储空间的模型数量 名称、路径和实例 ID 的调用者。 allocatedProjectPathLen:为接收项目路径分配的存储长度 allocatedModelPathLen:为接收模型路径分配的存储长度 allocatedMachineNameLen:分配的存储长度以接收机器名称 allocatedIpLen:为接收 IP 地址分配的存储长度
输出参数
numProjects:指向 API 将存储实际活动项目数的位置的指针。 numModels: 指向 API 将存储实际总数的位置的指针 所有活动项目的模型数量。 maxProjectPathLen: 指向 API 将存储最长项目路径长度的位置的指针。 maxModelPathLen: 指向 API 将存储最长模型路径长度的位置的指针。 maxMachineNameLen: 指向 API 将存储最长机器名称长度的位置的指针。 maxIpLen: 指向 API 存储长度的指针 最长的IP地址。 projectPaths: 字符串数组,API 将在其中存储活动项目配置文件的路径。 instanceIDs: 数组,API 将在其中存储活动项目的实例 ID。 machineNames: API 将存储机器名称的数组。 controllerIPs: API 将存储 IP 地址的数组。 modelPaths: 数组,API 将存储所有活动项目的模型路径。 numModelsPerProject: 数组,API 将在其中存储每个项目的模型数量。使用这些值来确定什么 型号属于什么项目。 modelIDs: 数组,API 将在其中存储所有模型的 ID 活跃的项目。 modelStates: API 将存储所有活动项目的模型状态的数组。
还有一个 C 程序使用 OpalGetActiveProjects() 函数来获取 projectPaths、machineNames 等。
#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);
}
【问题讨论】:
-
你不能,也没有办法在使用后正确销毁返回的字符串。此函数在本机代码中使用也不安全,因此使用 C++/CLI 也是一种废话。
标签: c# char marshalling param