Сбой программы при попытке вызвать функцию в C ++ DLL из C # - PullRequest
0 голосов
/ 17 октября 2018

У меня есть 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 за егополезный ответ.Но есть и другая функция, которая, как оказалось, не работает.Я пытаюсь распечатать результаты функции sin для аргументов в диапазоне от start до end с шагом step.

Вот часть кода C #, где происходит ошибка:

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

Выдает System.AccessViolationException.Это говорит о том, что есть попытка доступа к защищенной памяти.Я думаю, что это из-за этого среднего указателя в 5-й строке кода DLL.Есть ли способ преодолеть проблему?

...