代码之家  ›  专栏  ›  技术社区  ›  mll5

使用stringbuilder编组发出非托管调用

  •  1
  • mll5  · 技术社区  · 11 年前

    我想用 Reflection.Emit 生成的代码。

    我有一个dll,它定义了以下本机C函数。

    __declspec(dllexport) int WINAPI ChangeString(wchar_t *lpBuf, int nSize)
     {
         return swprintf_s(lpBuf, nSize, L"Value=%s\n", L"Something");
     }
    

    然后,我用上述函数的方法定义了一个C#接口。

    public interface IMyNative {   
    
        int ChangeString(StringBuilder sb, int size);
    }
    

    从这一点开始,我有一个简单的 MakeNative 函数,该函数使用 反射。发射 它实现了 IMyNative 界面为了生成与本机调用对应的方法,我执行以下操作:

    // MakeNative function, for brevity only revelant part is below.
    MethodBuilder methodBuilder = typeBuilder.DefineMethod("ChangeString",
         MethodAttributes.Public | MethodAttributes.Virtual,
         typeof(int), new Type[] { typeof(StringBuilder), typeof(int) });
    
    ILGenerator il = methodBuilder.GetILGenerator();
    
    // 0th arg is object itself, ignore
    il.Emit(OpCodes.Ldarg1);  // first arg
    il.Emit(OpCodes.Ldarg2);  // second arg
    
    // AddrOfNativeFunction is found using LoadLibrary & GetProcAddress
    il.Emit(OpCodes.Ldc_I8, AddrOfNativeFunction);
    il.EmitCalli(OpCodes.Calli, CallingConvetion.StdCall, typeof(int), new Type[] { typeof(StringBuilder), typeof(int) };
    il.Emit(OpCodes.Ret);
    

    然后我试着打电话 ChangeString 方法使用 StringBuilder :

    IMyNative impl = MakeNative();
    StringBuilder sb = new StringBuilder(100);
    impl.ChangeString(sb, 100);
    

    但程序崩溃 AccessViolationException 。可能有什么问题?

    1 回复  |  直到 11 年前
        1
  •  2
  •   usr    11 年前

    可能出了什么问题?

    你正在传递一个 StringBuilder 指向通过指针调用的函数。这可能是无法验证的IL。您的本机函数无法理解指向托管类的指针。

    您可能打算使用通常的PInvoke编组逻辑,但您没有使用PInvoke。因为这个原因,你没有得到编组。

    使用PInvoke。发出PInvoke方法并调用它。