0

我正在从 VBA 工作到 .NET。我有一个使用 CLI 和 stdcall 的接口的工作版本

我正在尝试删除对 C++ 2015 运行时产生的依赖,看起来我可以使用 UnmanagedExports 来做到这一点。

但我有几个问题。

  1. 我可以只使用“ref string”作为参数并让它工作吗?
  2. 如果是这样,我可以用“out string”替换它吗?
  3. 在这两种情况下,我是否必须进行任何字符串/字符串长度管理?

  4. 我目前将几个回调作为“int”传递。从我在别处看到的一个例子来看,它看起来像在 C# 端,使用它,我应该能够用 Func 替换这些参数以进行回调,例如 Function A(p1 as String, p2 as Long, p3 as String) as Long

任何建议将不胜感激。

4

1 回答 1

0

您需要 StrPtr 的组合,可能是 Access 端的 StrConv 和 .NET 端的 IntPtr:

        '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;
    }
于 2018-04-24T01:21:51.103 回答