У меня есть 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.Есть ли способ преодолеть проблему?