2017-01-20 14 views
0

Я пытаюсь обернуть dll C++, для которого у меня есть только файл заголовка. Функция Я пытаюсь получить работу в данный момент дает мне AccessViolationException:C# P/Invoke AccessViolationException при attepting для использования параметров строки

"Attempted to read or write protected memory. 
This is often an indication that other memory is corrupt." 

++ прототип функции С:

RunSimulation(LPCSTR, LPSTR); 

Между тем, мой C# обертка:

[DllImport("thedll.dll", EntryPoint = "RunSimulation")] 
public static extern uint RunSimulation(string simID, ref string outputID); 

Я подозреваю, что проблема связана с функцией C#, в частности с тем, как реализованы строки. Поскольку я относительно новичок в вызове платформы и тому подобное, я не уверен, как это сделать.

Если параметры строки являются указателями на то, где строки? Или может быть что-то еще с оберткой?

Edit:

Это как функция вызывается на управляемом конце вещей:

string outputID = ""; 

try 
{ 
    RunSimulation(id, ref outputID); 
} 
catch (Exception e) 
{ 
    Logging.Log_Warning.SendException("Threw an exception", e); 
} 

Edit 2:

При изменении второго параметра в StringBuilder , возникает одно и то же исключение. Единственное различие заключается в том, что разрыв исключения не останавливается на строке, где вызывается функция, Visual Studio открывает новую вкладку «Перерыв», говоря о том, что произошло исключение. В документации по функциям рекомендуется выделить 16 байтов или более, поэтому я использовал конструктор емкости со значениями 1024 и 4096 для тестирования.

Edit 3:

После выполнения чистой и перестраивать, проблема представлялась как ошибка водителя. Поскольку это показывает, что API работает, решение действительно должно было изменить мой параметр ref string на StringBuilder, как это предлагается в комментариях.

+1

Попробуйте использовать «StringBuilder» в качестве второго параметра с некоторой начальной настройкой емкости (используя этот конструктор (https://msdn.microsoft.com/en-us/library/h1h0a5sy (v = vs.110) .aspx? CS-копи-LANG = 1 & CS-LANG = CSharp # код-сниппет-1)). –

+2

Аргументы должны быть 'string simID, StringBuilder outputID', пожалуйста, обратитесь к бесчисленным другим вопросам и статьям об использовании' StringBuilder' таким образом. Абонент должен выделять достаточную память. Контракт с вызываемой вами функцией должен указывать, насколько велика эта строка. –

+2

У вас есть хороший ответ, так как вы получите такую ​​минимальную информацию. Если вам нужна дополнительная помощь, укажите [mcve]. Существует множество других способов, с помощью которых этот способ взаимодействия не срабатывает, и тот факт, что вы показываете такой маленький код, не помогает. –

ответ

0

Решение моей проблемы в конечном итоге заключалось в использовании StringBuilder вместо String, чтобы гарантировать, что пространство в памяти было выделено раньше времени. Так что моя подпись кончались выглядит как:

[DllImport("thedll.dll", EntryPoint = "RunSimulation")] 
public static extern uint RunSimulation(string simID, StringBuilder outputID); 

И использовать его:

string id = "someID"; 
int requiredSize = 512; 
StringBuilder outputID = new StringBuilder(requiredSize); 

RunSimulation(id, outputID); 

Надежда, что помогает!

 Смежные вопросы

  • Нет связанных вопросов^_^