尝试从C#调用C ++ DLL中的函数时程序崩溃

时间:2018-10-17 11:25:47

标签: c# c++ dll dllexport

我有一个C ++ dll,其中包含不同的三角函数和一些导出的函数,这些函数返回dll信息和结果:

#include "stdafx.h"
#include <cmath>
#include <iostream>

double(*mid)(double);

double csin(double x) {
    return std::sin(x);
}

double ccos(double x) {
    return std::cos(x);
}

double ctan(double x) {
    return std::tan(x);
}

double ccot(double x) {
    return 1 / std::tan(x);
}

extern "C" _declspec(dllexport) char* __stdcall get_name() {
    char * name = "Trigonometry";
    return name;
}

extern "C" _declspec(dllexport) char* __stdcall get_info() {
    char * name = "sin|cos|tan|cot";
    return name;
}

extern "C" _declspec(dllexport) void __stdcall set_func(char *name) {
    if (name == "sin") mid = &csin;
    if (name == "cos") mid = &ccos;
    if (name == "tan") mid = &ctan; 
    if (name == "cot") mid = &ccot;
}

extern "C" _declspec(dllexport) double __stdcall calc(double x){
    return mid(x);
};

在C#程序中,我尝试调用GetName()函数以获取我的dll的名称,但是该程序崩溃并显示消息,提示该程序已退出,代码为-1073740940(0xc0000374)。

这是程序崩溃的一部分代码(发生在最后一行执行时):

IntPtr plugin = LoadLibrary(filename);
if (plugin == IntPtr.Zero)
{
    Console.WriteLine("Failed to load plugin!");
    return;
}

IntPtr func_gn = GetProcAddress(plugin, "_get_name@0");
IntPtr func_gi = GetProcAddress(plugin, "_get_info@0");
IntPtr func_se = GetProcAddress(plugin, "_set_func@4");
IntPtr func_ca = GetProcAddress(plugin, "_calc@8");
if (func_gn == IntPtr.Zero || func_ca == IntPtr.Zero || func_gi == IntPtr.Zero || func_se == IntPtr.Zero)
{
    Console.WriteLine("Missing some functions!");
    return;
}

Base b = new Base(plugin,
      (Base.InfoDelegate)Marshal.GetDelegateForFunctionPointer(func_gn, typeof(Base.InfoDelegate)),
      (Base.InfoDelegate)Marshal.GetDelegateForFunctionPointer(func_gi, typeof(Base.InfoDelegate)),
      (Base.SetDelegate)Marshal.GetDelegateForFunctionPointer(func_se, typeof(Base.SetDelegate)),
      (Base.CalcDelegate)Marshal.GetDelegateForFunctionPointer(func_ca, typeof(Base.CalcDelegate)));

Console.WriteLine("Plugin {0} loaded", b.GetName()); // <- crash here

Base类:

class Base
{
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate string InfoDelegate();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void SetDelegate(string fname);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate double CalcDelegate(double x);

    public IntPtr dll;
    public InfoDelegate GetName;
    public InfoDelegate GetInfo;
    public SetDelegate SetFunc;
    public CalcDelegate Calc;

    public Base(IntPtr dll, InfoDelegate name, InfoDelegate info, SetDelegate set, CalcDelegate calc)
    {
        this.dll = dll;
        this.GetInfo = info;
        this.GetName = name;
        this.SetFunc = set;
        this.Calc = calc;
    }
}

执行上述行时,控制台中没有任何内容。它只是关闭而没有任何错误窗口。

什么是错误以及如何解决?

编辑

感谢Hans Passant的帮助。但事实证明,还有另一个功能不起作用。我尝试通过start步骤为endstep之间的参数打印sin函数的结果。

这是C#代码中发生错误的部分:

plugin.SetFunc("sin");
Console.WriteLine("Result:");
for (double i = start; i <= end; i += step)
{
    Console.WriteLine(plugin.Calc(i)); // <- crash here
}

它抛出System.AccessViolationException。它表示正在尝试访问受保护的内存。我认为这是因为dll代码第5行中的中间指针。有办法解决这个问题吗?

0 个答案:

没有答案