Неуправляемый экспорт Роберта Гизеке - OUT strings
Я работаю из VBA в.NET. У меня есть рабочая версия интерфейса с использованием CLI и stdcall
Я пытаюсь удалить полученную зависимость от среды выполнения C++ 2015, и похоже, что я могу сделать это с помощью UnmanagedExports.
Но у меня есть пара вопросов.
- Могу ли я просто использовать "ref string" в качестве параметра и заставить его работать?
- Если так, могу ли я заменить его на "out string"?
В любом случае, я должен сделать какое-либо управление длиной строки / строки?
В настоящее время я передаю пару обратных вызовов как "int". Из примера, который я видел в другом месте, похоже, что на стороне C#, используя его, я должен иметь возможность заменить эти параметры на Func для обратного вызова, такого как функция A(p1 как String, p2 как Long, p3 как String) как Long
Любые советы будут высоко ценится.
1 ответ
Вам нужна комбинация StrPtr, возможно, StrConv на стороне доступа и IntPtr на стороне.NET:
'VBA7
Private Declare PtrSafe Function Command Lib "External.dll" (ByVal CommandName As String, ByVal Result As LongPtr, ByRef ResultLength As Long) As Long
'VBA pre7
Private Declare Function Command Lib "External.dll" (ByVal CommandName As String, ByVal Result As Long, ByRef ResultLength As Long) As Long
'Example to use.
'Result will be up to "i" characters - no new string involved
Dim i As Long, x As Long, strResult As String
i = 100
strResult = Space(i)
x = Command(CommandName, Arguments, StrPtr(strResult), i)
Если вы используете StrConv, тип строки зависит от вас. Если вы этого не сделаете, указатель будет указывать на массив Unicode.
Сторона C#:
[DllExport("Command", CallingConvention.StdCall)]
public static int Command(string commandName, string arguments, IntPtr result, out /*or ref*/ int resultLength)
{
string inputStr = Marshal.PtrToStringUni(result); //Unicode
resultLength = inputStr.Length;
int x = MainFunc.Command(commandName, arguments, ref inputStr);
if(null == inputStr)
{
inputStr = "";
}
if(inputStr.Length > resultLength)
{
inputStr = inputStr.Substring(0, resultLength);
}
byte[] outputBytes = Encoding.Unicode.GetBytes(inputStr);
Marshal.Copy(outputBytes, 0, result, outputBytes.Length);
resultLength = inputStr.Length;
return x;
}