본문 바로가기
C++ Programming

[C++] DLL 로드해서 사용하기

by TYB 2024. 10. 23.
반응형

DLL 만들기(Visual Studio)

최초 생성하면 아래 코드가 기본으로 있음.// dllmain.cpp : DLL 애플리케이션의 진입점을 정의합니다.#include "pch.h"BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_ca

program-developers-story.tistory.com

이전 글에서 DLL 만드는 방법에 대한 소개가 있음.


 
이번 글에선 DLL 로드해서 함수 사용해볼거임.
 
개발 환경: C++ builder 11.3 
 
컴포넌트 추가 어떻게 하는지는 생략하겠음.
 

이렇게 간단하게 add 할 수 있게 추가만 해주고

버튼하나 만들어 줘야겠져?

요렇게 추가해주고
클릭 시 이벤트 추가

 
코드 구현
Unit2.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
	: TForm(Owner)
{
	Row=SGTitle->RowCount;
    Col=SGTitle->ColCount;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormShow(TObject *Sender)
{
	SGTitle->Cells[0][0]="title";
	for(int row = 0; row<Row; row++)
	{
		for(int col = 0; col<Col; col++)
		{
            SGTitle->Cells[col][row]=col+row*Row;
		}
	}
	LoadDLL();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
    UnloadDLL();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::BtnCalculateClick(TObject *Sender)
{
	String A = EditA->Text;
	String B = EditB->Text;
	int a = A.ToInt();
	int b = B.ToInt();
	//여기까지가 UI 상입력한 숫자값 받아오는 부분이고

	//아래에 입력받은 숫자값을 DLL에 추가해주면 되겠죠?
	if (MyFunction && Add)
	{
		MyFunction();  // DLL의 함수 호출
		int result = Add(a, b);  // Add 함수 호출
		EditC->Text =IntToStr(result);
		STDllStatus->Caption = "DLL 로드 성공 및 계산 완료";
	}
	else
	{
		STDllStatus->Caption = "DLL을 로드하지 못했습니다.";
	}

}
//---------------------------------------------------------------------------
// DLL을 로드하는 함수
void TForm2::LoadDLL() {
	//HINSTANCE hInstance = LoadLibrary(L"C:\\Users\\wooch\\OneDrive\\문서\\Embarcadero\\Studio\\Projects\\MyDLibrary.dll");
	HINSTANCE hInstance = LoadLibrary(L"MyDLibrary.dll");
	if (!hInstance) {
        DWORD error = GetLastError();
			STDllStatus->Caption =  error ;
		return;
    }

    // 함수 포인터에 DLL의 함수 주소를 할당
    MyFunction = (VoidFunction)GetProcAddress(hInstance, "MyFunction");
    Add = (AddFunction)GetProcAddress(hInstance, "Add");

    if (!MyFunction || !Add) {
        std::cerr << "함수를 찾을 수 없습니다." << std::endl;
        FreeLibrary(hInstance);
        hInstance = nullptr;
    }
}
//---------------------------------------------------------------------------
// DLL을 해제하는 함수
void TForm2::UnloadDLL() {
    if (hInstance) {
        FreeLibrary(hInstance);
        hInstance = nullptr;
    }
}
//---------------------------------------------------------------------------

 
Unit2.h

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H


//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Grids.hpp>
#include <Data.DB.hpp>
#include <Data.Win.ADODB.hpp>
//---------------------------------------------------------------------------
#include <windows.h>  // LoadLibrary와 GetProcAddress 사용을 위해 필요
//---------------------------------------------------------------------------
// DLL에서 가져올 함수 포인터 선언
typedef void (*VoidFunction)();
typedef int (*AddFunction)(int, int);


class TForm2 : public TForm
{
__published:	// IDE-managed Components
	TStringGrid *SGTitle;
	TADOConnection *ADOConnection1;
	TEdit *EditA;
	TEdit *EditB;
	TStaticText *StaticText1;
	TStaticText *StaticText2;
	TButton *BtnCalculate;
	TStaticText *STDllStatus;
	TEdit *EditC;
	void __fastcall FormShow(TObject *Sender);
	void __fastcall BtnCalculateClick(TObject *Sender);
	void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
private:	// User declarations
	VoidFunction MyFunction;  // 함수 포인터 변수
	AddFunction Add;          // 함수 포인터 변수
	HINSTANCE hInstance;      // DLL 핸들
public:		// User declarations
    int Row,Col;
	__fastcall TForm2(TComponent* Owner);
    void LoadDLL();  // DLL을 로드하는 함수 선언
    void UnloadDLL();  // DLL을 해제하는 함수 선언
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif

 
unit2.dfm
 

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 441
  ClientWidth = 624
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  OnClose = FormClose
  OnShow = FormShow
  TextHeight = 15
  object SGTitle: TStringGrid
    Left = 472
    Top = 352
    Width = 612
    Height = 401
    TabOrder = 0
    Visible = False
    RowHeights = (
      24
      24
      24
      24
      24)
  end
  object EditA: TEdit
    Left = 56
    Top = 80
    Width = 121
    Height = 23
    TabOrder = 1
  end
  object EditB: TEdit
    Left = 208
    Top = 80
    Width = 121
    Height = 23
    TabOrder = 2
  end
  object StaticText1: TStaticText
    Left = 190
    Top = 84
    Width = 12
    Height = 19
    Caption = '+'
    TabOrder = 3
  end
  object StaticText2: TStaticText
    Left = 335
    Top = 84
    Width = 12
    Height = 19
    Caption = '='
    TabOrder = 4
  end
  object BtnCalculate: TButton
    Left = 488
    Top = 79
    Width = 75
    Height = 25
    Caption = 'Calculate'
    TabOrder = 5
    OnClick = BtnCalculateClick
  end
  object STDllStatus: TStaticText
    Left = 80
    Top = 44
    Width = 4
    Height = 4
    TabOrder = 6
  end
  object EditC: TEdit
    Left = 353
    Top = 80
    Width = 121
    Height = 23
    TabOrder = 7
  end
  object ADOConnection1: TADOConnection
    Left = 544
    Top = 392
  end
end

 
문제가 많음.
1번 문제는 builder는 32bit 까지만 지원해서 64bit dll이 로드가 안됨.
                visual studio로 돌아가서 프로젝트 설정 변경해서 로드함.
2번 문제는 DLL 로드가 안되던 문제.
                 오류코드 216은 dll로드가 안된 경우 발생함. 이게 발생하면 dll 경로 먼저 체크해주면 됨.
                프로젝트 경로랑 동일한 경로에 dll을 위치시켰으나, 로드가 안됨. 이유를 모르겠음.
                 절대경로로 그냥 지정해버리는 걸로 해결함.

A와 B에 값 넣어준 다음에 Calculate 버튼 눌러주면 이전 글 DLL에서 윈도우 메시지 팝업 띄우게 하는 함수가 먼저 호출됨.
확인 버튼 누르면 계산 되서 적용됨.

 
 
 


해보다가 안 사실인데 프로젝트 위치가 cpp 파일 있는 곳이 아니라 컴파일 된 exe 파일이 있는 위치였음.

해당 위치에 위치시켜주니 정상적으로 로드함.

 

반응형