Выделение родного.dll в C# с несколькими указателями
Имея следующий код в C++:
- nConId - это идентификатор соединения
- pParName имя параметра
- pSubName Имя субпараметра (если есть)
- pValue_out указатель на массив символов длины FCL_PAR_VALUE_LENGH
- nValueSize реальный размер вектора pValue_out (не менее 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, поэтому я предполагаю, что в моем вызове что-то не так.
Неужели мой маршал не прав? Что я должен изменить в коде, чтобы получить хороший ответ?
PS: я тоже знаю, что звонок тоже что-то возвращает aParValue
,
1 ответ
Решение
Ты слишком много работаешь с этими char*
s. Совершенно законно (и поощряется) 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
так что я предполагаю, что вы исключили это как проблему.