将本机非托管 C++ DLL 加载到托管 C# 应用程序会导致 DLL 输出垃圾

帕特里克·W。

我有一个本机的非托管 C++ DLL (symulator.dll),我必须从托管 C# 应用程序加载和调用它。

DLL 使用 C++ 类和动态内存分配(通过new操作符)。

它导出一个被调用的函数Init,其定义如下:

extern "C" __declspec( dllexport ) int Init( void )
{
    sym = new CSymulator();
    sym->Init();
    return 0;
}

CSymulatorDLL 中包含类有一个相当简单的构造函数:

CSymulator::CSymulator( void )
{
    memset( mem, 0, sizeof( mem ) );
    memset( &rmr, 0, sizeof( rmr ) );
    md = 0;
    ma = 0;
    tacts = 0;
}

DLL导出CSymulator::Init()Init()函数调用方法定义如下:

int CSymulator::Init( void )
{
    int *a = new int;

    *a = 1;

    FILE *f = fopen( "tmp.log", "wb" );
    fprintf( f, "%i", *a );
    fclose( f );

    delete a;
    return 0;
}

我正在使用以下代码将本机 C++ DLL 加载到托管 C# 应用程序中:

public partial class Form1 : Form
{
    public IntPtr SimHandle;

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr LoadLibrary(string libname);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern bool FreeLibrary(IntPtr hModule);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

    delegate int SimInit();

    SimInit DLL_Init;

    public void InicjujDLL()
    {
        IntPtr adres;

        adres = GetProcAddress(SimHandle, "Init");
        DLL_Init = (SimInit)Marshal.GetDelegateForFunctionPointer(adres, typeof(SimInit));

        int rc = DLL_Init();
    }

    private void WczytajDLL()
    {
        String fileName = "D:\\prg\\kompilator\\Debug DLL\\symulator.dll";

        SimHandle = LoadLibrary(fileName);
        if (SimHandle == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new Exception(string.Format("Blad przy wczytywaniu biblioteki ({0})", errorCode));
        }
        else
        {
            InicjujDLL();
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        WczytajDLL();
    }
}

此代码应生成一个名为tmp.log的文件,其中包含 的内容1但出于某种原因,tmp.log包含垃圾数据(一个随机的 32 位整数值而不是 1;例如,2550276)。

它不是产生垃圾输出的唯一函数。任何尝试动态分配内存的 DLL 函数在这样做后都无法使用它。

就好像本机 C++ DLL 以某种方式通过 C# 垃圾收集器清除了其内存。

如何防止这种行为?

Shibumi Tait

等一下:看看下面的参考:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int MultiplyByTen(int numberToMultiply);

我没有注意到您的委托没有相同的属性。

作为参考,我没有看到您执行 LoadLibrary: Dynamically Loading a Native Library 的方式有任何异常

我自己使用确切的参考做了这个,没有问题。我建议暂时删除在 DLL 内执行的所有代码,并只做一个简单的传递值。现在 Init() 总是返回 0。尝试别的东西,因为你之前已经将内存清零,得到零可能只是 mem-zero 操作的副作用。返回 1974 年什么的。

确保您启用了允许不安全代码并使用内存查看器查看堆栈(您将返回一个指针,以便您有一个起点)。如果你在 IL 旁边这样做,你可能会发现你的记忆被破坏了。

HTH

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用非托管代码的C#应用程序加载msvcr90.dll + msvcr80.dll + msvcr100.dll。这有关系吗?

在C#中使用非托管DLL

将托管的C#DLL包含到非托管的C ++ DLL中-全部集中在一个文件中

将依赖的托管DLL添加到非托管C ++项目

C#DLL异常未在非托管C ++中捕获

在C ++ / FORTRAN中使用非托管C#-DLL

在C#项目中使用托管dll(使用非托管dll)

将字节数组从 C++ 非托管 dll 传递到 C# unity

将C#结构传递给非托管C ++ DLL时出现SafeArrayTypeMismatchException

C#将指向结构(包含不可复制类型)的指针传递给非托管C ++ DLL

从非托管C#DLL返回列表/数组

P /调用-从C#调用非托管DLL

C-从非托管DLL正确导入stdcall函数

NUnit C#使用DllImport的非托管dll引发BadImageFormatException

从非托管 C DLL 转换混合类型返回数据?

C#中非托管DLL的调用约定

ASP.NET应用程序无法加载非托管DLL

无法使用C#和Robert Giesecke的非托管导出工具创建非托管dll

本机DLL-C#

C#加载本机dll动态简单

C ++访问DLL加载

我可以在非托管Delphi EXE中使用托管C#DLL吗?

C#DLL注入未加载DLL

动态加载包装C ++ DLL的.NET DLL

区别:本机 DLL、UWP DLL 和 C++/CLI DLL

从具有托管输出的C#DLL返回字符串到Inno Setup脚本

如何从Visual Studio.NET或Visual Studio 2005中的本机Visual C ++代码调用托管DLL

使用Mupen64Plus非托管C dll API命令填充C#结构

C#到非托管C ++ DLL访问冲突/“框架不在模块中”