Смущен из-за точек входа DLL (исключение не найдено) - PullRequest
9 голосов
/ 02 сентября 2011

Я пытаюсь научиться использовать DLL в C #.У меня есть очень простая DLL, чтобы проверить основы.

// MainForm.cs


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace DLL_Test
{
        public partial class Form1 : Form
        {
            [DllImport("TestDLL.dll",
                        EntryPoint="?Add@@YGHHH@Z",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.StdCall)]
            public static extern int Add(int a, int b);

            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                int num;
                try
                {
                    num = Add(2, 3);
                    richTextBox1.AppendText(num.ToString() + "\n");
                }
                catch (DllNotFoundException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                catch (EntryPointNotFoundException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
             }
         }
}

И код DLL:

// TestDLL.cpp

__declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}

dumpbin возвращает следующее:

ordinal   hint   RVA        name
      1      0   00011005   ?Add@@YGHHH@Z = @ILT+0(?Add@@YGHHH@Z)

This(и другие попытки, перечисленные ниже), все вернули одно и то же исключение:

System.EntryPointException: Unable to find entry point named "..."

Так что я не знаю, как решить эту проблему.Возможно, я не понимаю, как DllMain функционирует как точка входа C # для DLL.TestDLL.dll работает, когда я тестирую его в приложении C ++.

После поиска справки я попытался внести следующие изменения:

// TestDLL.cpp

extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}

, что приводит к этому из dumpbin

ordinal   hint   RVA        name
      1      0   00011005   _Add@8 = @ILT+135(_Add@8)

Таким образом, я изменил свой код C #:

 // MainForm.cs

...

[DllImport("TestDLL.dll",
                        EntryPoint="_Add",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.StdCall)]
            public static extern int Add(int a, int b);

...

Я также пытался __cdecl:

// TestDLL.cpp

extern "C" __declspec(dllexport) int __cdecl Add(int a, int b) {
return(a + b);
}

.

// MainForm.cs

...

[DllImport("TestDLL.dll",
                        EntryPoint="_Add",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.Cdecl)]
            public static extern int Add(int a, int b);

...

Возможно, я неправильно понимаю соглашение о вызовах.Любая помощь будет принята с благодарностью.Спасибо.

Ответы [ 3 ]

16 голосов
/ 02 сентября 2011

использование

extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) { ... }

и

[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Stdcall)] 
public static extern int Add(int a, int b); 

extern "C" предотвратит искажение имени с параметрами и типом возврата, таким как ?Add@@YGHHH@Z. __stdcall добавит _ и добавит @8: _Add@8 (где 8 - общий размер аргументов). Обратите внимание, что это также влияет на то, как параметры помещаются в стек.

В вашем выражении DLLImport, поскольку вы указываете CallingConvention.StdCall, вам не нужно указывать искажение имени. Просто назовите обычное имя (Add), и .NET позаботится о искалечении имени (_Add@8).

Обратите внимание, что вы должны указать CallingConvention или .NET не сгенерирует правильный код для отправки аргументов в стек

0 голосов
/ 27 мая 2014

Для дальнейшего использования: у меня была похожая проблема, я решил создать EMPTY C ++ dll проект. Вероятно, стандартный шаблон Visual Studio вызывает некоторые проблемы.

Ссылка на эту ссылку: http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w

0 голосов
/ 02 сентября 2011

Должно работать следующее.

Unmanged:

extern "C" __declspec(dllexport) int Add(int a, int b) 
{
    return(a + b);
}

Управляется:

class Program
{
    [DllImport("TestDLL.dll")]
    public static extern int Add(int a, int b);

    static void Main()
    {
        Console.WriteLine(Add(1, 2));
    }
}
...