在 C++ 中具有以下代码:
- nConId is Connection Identifier
- pParName the parameter name
- pSubName the subParameter Name (if any)
- pValue_out a pointer to a char array of lenght FCL_PAR_VALUE_LENGH
- nValueSize the real size of pValue_out vector (at least FCL_PAR_VALUE_LENGH)
extern "C" MY_API int ReadParameter(const ConnectionId_T nConId, const char* pParName,
const char *pSubName, char *pValue_out, const int nValueSize );
我的尝试是:
[DllImport("mydll.dll", CharSet = CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
public static extern int ReadParameter(ConnectionId_T pConId, IntPtr pParName,
ref IntPtr pSubName, ref IntPtr[] pValue_out, int nValueSize);
我使用以下代码来调用该函数:
# nConId is returned from another function and the his value is 0
public const int FCL_PAR_VALUE_LENGH = 128;
string param_string = "AUXF";
IntPtr pParName = (IntPtr)Marshal.StringToHGlobalAnsi(param_string);
string subparam_string = "T";
IntPtr pSubName = (IntPtr)Marshal.StringToHGlobalAnsi(subparam_string);
IntPtr[] aParValue = new IntPtr[FCL_PAR_VALUE_LENGH];
int returnedValue = ReadParameter(nConId, pParName, ref pSubName,
ref aParValue, FCL_PAR_VALUE_LENGH);
当我运行代码时,我得到一个AccessViolationException,所以我猜我的调用有问题。
我的编码(marshal)错了吗?为了获得良好的响应,我必须在代码中更改哪些内容?
PS:我也知道该调用还会向 aParValue
返回一些内容。
最佳答案
您对这些 char*
的工作太辛苦了。将 System.String
编码用于输入,并编码 StringBuilder
用于输出是完全合法(并鼓励)的。
[DllImport("mydll.dll", CharSet = CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
public static extern int ReadParameter(
ConnectionId_T pConId,
string pParName,
string pSubName,
StringBuilder pValue_out,
int nValueSize);
使用
const int sbLength = 256; //use a domain relevant value
StringBuilder sb = new StringBuilder(sbLength + 1); //for null character, hard to say if you need it without seeing the C++ code, but easier to just add it than find out.
int result = ReadParameter(conId, "paramname", "paramsubname", sb, sbLength);
您没有给出有关 ConnectionId_T
基础类型的任何指示,因此我假设您已排除该问题。
关于c# - 使用多个指针在 C# 中编码 native .dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37525627/