Эксепшен при загрузке dll, написанной на С - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. Разбираюсь с мехинизмом загрузки dll, написанной на С, C# приложением. Нашел простенький пример и слегка его изменил: Сама DLL:
#include <iostream>
#include <windows.h>
 
using namespace std;
 
void initialize() throw()
{
        // Инициализация после подключения DLL к процессу.
        cout << "DLL: loaded." << endl;
}
 
// API DLL - экспортируемые функции ///////////////////////////////////////////
 
extern "C" void __declspec(dllexport) Test(int i)
{
        cout << "DLL: called 'Test'" << i << endl;
}
 
///////////////////////////////////////////////////////////////////////////////
 
void finalize() throw()
{
        // Завершающие действия перед отключением DLL от процесса.
        cout << "DLL: is free." << endl;
}
 
BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD dwReason, LPVOID lpReserved) throw()
{
        switch(dwReason)
        {
        case DLL_PROCESS_ATTACH:
                initialize();
                break;
        case DLL_PROCESS_DETACH:
                finalize();
                break;
        }
        return TRUE;
}
Приложение:
using System;
using System.Runtime.InteropServices;
 
namespace App
{
    class Program
    {
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern IntPtr LoadLibrary(string lpFileName);
 
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern bool FreeLibrary(IntPtr hModule);
 
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
 
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern uint GetLastError();

        delegate void TestDelegate(int i);

        static void Main(string[] args)
        {
            Console.WriteLine("Application: begin.");
            IntPtr hModule = LoadLibrary("dll.dll");
            if (hModule == IntPtr.Zero)
            {
                Console.WriteLine("Application: Can't load DLL. Error # {0}.", GetLastError());
            }
            else
            {
                IntPtr ptrTest = GetProcAddress(hModule, "Test");
                if (ptrTest == IntPtr.Zero)
                {
                    Console.WriteLine("Application: Function 'Test' not found in DLL.");
                }
                else
                {
                    TestDelegate Test = Marshal.GetDelegateForFunctionPointer(ptrTest, typeof(TestDelegate)) as TestDelegate;
 
                    /// Работа с DLL //////////////////////////////////////////
 
                    Test(7);
 
                    ///////////////////////////////////////////////////////////
                }
                FreeLibrary(hModule);
            }
            Console.WriteLine("Application: end.");
            Console.ReadKey();
        }
    }
}
В результате возникает эксепшен: PInvokeStackImbalance was detected A call to PInvoke function 'ConsoleApplication1!ConsoleApplication1.Program+TestDelegate1::Invoke' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. Можно конечно сделать так:
using System;
using System.Runtime.InteropServices;
 
namespace App
{
    class Program
    {
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern IntPtr LoadLibrary(string lpFileName);
 
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern bool FreeLibrary(IntPtr hModule);
 
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
 
        [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi)]
        static extern uint GetLastError();
 
        [DllImport("new22.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        static extern void Test(int i);
 
        static void Main(string[] args)
        {
            Console.WriteLine("Application: begin.");
            Test(7);
            Console.WriteLine("Application: end.");
            Console.ReadKey();
        }
    }
}
Тогда эксепшен не возникает. Но в этом случае отсутствует проверка на загрузку dll. Что не очень хорошо. Подскажите, пожалуйста, как можно добавить проверку на загрузку dll во втором случае, или исправить возникновение эксепшена в первом?

Решение задачи: «Эксепшен при загрузке dll, написанной на С»

textual
Листинг программы
 [DllImport("new22.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        static extern void Test(int i);

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

15   голосов , оценка 3.8 из 5
Похожие ответы