Не находит функцию в .dll (c#)
Не находит функцию в .dll, которую подключаю(funcPtr == 0). Предполагаю, что имя функции либо кодируется, либо меняется как-то внутри, но сам пока не могу понять.
Программа:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Lab1Dynamic
{
class Program
{
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", SetLastError = true, EntryPoint = "GetProcAddress")]
static extern IntPtr GetProcAddressOrdinal(IntPtr hModule, IntPtr procName);
private delegate double fDelegate(double x, double y);
static void Main(string[] args)
{
var dllPath = "MyLibrary.dll";
IntPtr dllInstance = LoadLibrary(dllPath);
while (dllInstance == IntPtr.Zero)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Can't load DLL " + dllPath);
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine("Write the path below...");
dllPath = Console.ReadLine();
dllInstance = LoadLibrary(dllPath);
}
string fname = "f";
IntPtr funcPtr = GetProcAddress(dllInstance, fname);
fDelegate fd = (fDelegate)Marshal.GetDelegateForFunctionPointer(funcPtr,
typeof(fDelegate));
var y = fd(1.0, 2.0);
}
}
}
DLL:
using System;
namespace MyProj
{
public class MyLibrary
{
public static double f(double x, double y) => 3 * Math.Sin(x) + 2 * Math.Cos(y);
}
}
DLL(C++, VS2019): MyLib.h:
#pragma once
extern "C" __declspec(dllexport) double f(const double x, const double y);
MyLib.cpp:
#include "MyLib.h"
#include "pch.h"
#include <cmath>
double f(const double x, const double y)
{
return 3 * sin(x) + 2 * cos(y);
}
P.S. Делал по гайду от MDSN тут
Ответы (1 шт):
Первое на что стоит обратить внимание, это на то, какое соглашение используется в вашем проекте:
Далее, при формировании делегата на неуправляемую импортируемую функцию, вам необходимо добавить соответствующий атрибут:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate double ImportFDelegate(double x, double y);
Далее при запросе указателя на неуправляемую функцию, убедитесь что вы передаете правильное имя функции:
В моем случае:
C:\Users\ヒミコ\source\repos\SO\Debug>dumpbin /exports MyLib.dll
Microsoft (R) COFF/PE Dumper Version 14.24.28316.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file MyLib.dll
File Type: DLL
Section contains the following exports for MyLib.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 0001117C f = @ILT+375(_f) // Здесь указано экспортированное имя, и реальное, реальное с подчеркиванием
// подробнее на MSDN https://docs.microsoft.com/ru-ru/cpp/cpp/argument-passing-and-naming-conventions?view=vs-2019
Summary
1000 .00cfg
1000 .data
1000 .idata
1000 .msvcjmc
2000 .rdata
1000 .reloc
1000 .rsrc
6000 .text
10000 .textbss
C:\Users\ヒミコ\source\repos\SO\Debug>
Так же убедитесь в том что разрядность проектов соответствует, т.е. если библиотека x86, то и проект на c# x86, с x64 то же самое.
Далее просто привожу код исправленный:
class Program
{
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.Winapi)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeLibrary(IntPtr moduleHandle);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate double ImportFDelegate(double x, double y);
static void Main(string[] args)
{
string dllPath = "MyLibrary.dll";
IntPtr dllInstance = LoadLibrary(dllPath);
while (dllInstance == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
Win32Exception exception = new Win32Exception(errorCode);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Unable to load library {1}:\n\t{0}", exception.Message, Path.GetFileName(dllPath));
Console.ResetColor();
Console.WriteLine("Write the path below...");
dllPath = Console.ReadLine();
dllInstance = LoadLibrary(dllPath);
}
const string functionName = "f";
IntPtr funcPtr = GetProcAddress(dllInstance, functionName);
if (funcPtr == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
Win32Exception exception = new Win32Exception(errorCode);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Unable to get address of function: {0}\n\t{1}", functionName, exception.Message);
return;
}
ImportFDelegate fd = (ImportFDelegate)Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(ImportFDelegate));
double result = fd(1.0, 2.0);
Console.WriteLine("Imported function return result: {0:N}", result);
FreeLibrary(dllInstance);
}
}
Ну и собственно вывод программы:
Unable to load library MyLibrary.dll:
Не найден указанный модуль
Write the path below...
MyLib.dll
Imported function return result: 1,69
