it-source

C/C++로 DLL을 컴파일하여 다른 프로그램에서 호출합니다.

criticalcode 2023. 1. 13. 19:51
반응형

C/C++로 DLL을 컴파일하여 다른 프로그램에서 호출합니다.

함수를 하나 또는 두 개 내보내는 단순하고 간단한 DLL을 만든 다음 다른 프로그램에서 호출하려고 합니다.지금까지 내가 찾아본 모든 곳은 복잡한 문제들, 서로 다른 연결 방법들, 아직 존재조차 깨닫지 못한 이상한 문제들...다음과 같은 방법으로 시작하고 싶습니다.

다음과 같은 함수를 내보내는 DLL을 만듭니다.

int add2(int num){
   return num + 2;
}

int mult(int num1, int num2){
   int product;
   product = num1 * num2;
   return product;
}

MinGW로 컴파일을 하고 있는데, C++로 컴파일을 하는 것에 실제 차이가 있다면 그것들도 알고 싶습니다.그 DLL을 다른 C(및 C++) 프로그램에 로드하고 그 DLL에서 함수를 호출하는 방법을 알고 싶습니다.여기서의 목표는 DLL을 잠시 사용한 후 DLL을 비주얼 베이직으로 로드함으로써 C(+) 코드에 대한 VB 프런트 엔드를 만드는 것입니다(Visual Studio 6을 가지고 있기 때문에 DLL을 호출하는 폼 상의 오브젝트에 대한 폼과 이벤트를 만들고 싶을 뿐입니다).

DLL을 작성하기 위해 gcc(/g++)를 호출하는 방법과 내보내기 파일을 쓰는(/생성) 방법을 알아야 합니다.DLL에서 할 수 있는 것과 할 수 없는 것(예를 들어 VB 프런트 엔드에서 포인터/레퍼런스로 인수를 취득할 수 있습니까?)DLL은 프론트 엔드의 이론 함수를 호출할 수 있습니까?또는 기능 포인터를 VB에서 가져와 호출할 수 있는지조차 알 수 없습니다.변종을 DLL에 넘길 수 없을 것 같은데...하지만 그게 내가 아는 전부야

다시 갱신하다

gcc로 컴파일해서 실행한 dll을 만드는 방법을 알아냈어

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a

그리고 나서 다른 프로그램을 로드해서 기능을 테스트해 봤는데, 조언해 주셔서 감사합니다만, 이렇게 VB6로 로드해 보았습니다.

Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer

폼에서 add2(text1.text)를 호출했는데 런타임 오류가 발생했습니다.

"C:\c\dll\mydll.dll에서 DLL 진입점 add2를 찾을 수 없습니다."

DLL용으로 컴파일한 코드는 다음과 같습니다.

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

EXPORT int __stdcall add2(int num){
  return num + 2;
}

EXPORT int __stdcall mul(int num1, int num2){
  return num1 * num2;
}

C프로그램에서 이렇게 호출하는 것은 효과가 있었습니다만,

#include<stdio.h>
#include<windows.h>

int main(){

  HANDLE ldll;
  int (*add2)(int);
  int (*mul)(int,int);

  ldll = LoadLibrary("mydll.dll");
  if(ldll>(void*)HINSTANCE_ERROR){
    add2 = GetProcAddress(ldll, "add2");
    mul = GetProcAddress(ldll, "mul");
    printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
  } else {
    printf("ERROR.");
  }

}

좋은 생각 있어?

해결했다

이전 문제를 해결하려면 다음과 같이 컴파일해야 했습니다.

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias

VB6에서 이 API 호출을 사용합니다.

Public Declare Function add2 Lib "C:\c\dll\mydll" _
    (ByVal num As Integer) As Integer

저는 ByVal 또는 ByRef를 명시적으로 지정하는 것을 잊지 않도록 배웠습니다.- 3048처럼 보이는 인수 주소를 방금 받았습니다.

다음은 MinGW를 사용한 DLL 구축에 관한 간단한 절차입니다.

먼저 함수를 내보낼 수 있도록 마킹해야 합니다.이러한 기능을 DLL 발신자가 사용할 수 있습니다.이렇게 하려면 다음과 같이 수정하십시오(예:

__declspec( dllexport ) int add2(int num){
   return num + 2;
}

그런 다음 함수가 funcs.c라는 파일에 있다고 가정하면 다음과 같이 컴파일할 수 있습니다.

gcc -shared -o mylib.dll funcs.c

공유 플래그는 GCC에 DLL을 생성하도록 지시합니다.

DLL이 실제로 함수를 내보냈는지 여부를 확인하려면 무료 Dependency Walker 도구를 사용하여 DLL을 검사합니다.

DLL 구축에 필요한 모든 플래그 등을 자동화하는 무료 IDE는 다음과 같은 우수한 코드를 참조하십시오.블록 - MinGW에서 매우 잘 동작합니다.

편집: 이 주제에 대한 자세한 내용은 MinGW Wiki에서 Visual Basic과 함께 사용할 MinGW DLL 만들기 문서를 참조하십시오.

한 가지 차이밖에 없다.C++는 잘 관리하거나 이름을 붙여야 합니다.단, 윈도에서는 1) DLL에서 내보낼 함수를 디코딩하는 데 주의해야 합니다 2) 내보낸 모든 기호를 나열하는 이른바 .def 파일을 작성합니다.

Windows 에서는, DLL 를 컴파일 하는 동안,

__declspec(dllexport)

단, 사용 중에는 __declspec(syslog import)을 입력해야 합니다.

그래서 그렇게 하는 일반적인 방법은

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

이름이 EXPORT로 되어 있는 경우가 많기 때문에 조금 혼란스럽습니다.하지만 그것은 대부분의 머리글에서 찾을 수 있는 것입니다.따라서 위의 #define을 사용하여 작성해야 합니다.

int DLL_EXPORT 추가...int DLL_EXPORT 멀티...

공유 라이브러리를 빌드할 때는 프리프로세서 디렉티브 BUILD_DLL을 추가해야 합니다.

프리드리히 경위해서

방법은 다음과 같습니다.

인 .h

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

extern "C" // Only if you are using C++ rather than C
{    
  EXPORT int __stdcall add2(int num);
  EXPORT int __stdcall mult(int num1, int num2);
}

.cpp로

extern "C" // Only if you are using C++ rather than C
{    
EXPORT int __stdcall add2(int num)
{
  return num + 2;
}


EXPORT int __stdcall mult(int num1, int num2)
{
  int product;
  product = num1 * num2;
  return product;
}
}

매크로는 모듈(즉, .cpp 파일)이 dll 정보를 외부에 제공하고 있음을 알려줍니다..h 파일을 삽입하는 사람들은 동일한 함수를 Import하고 싶어하기 때문에 EXPORT를 링커에게 Import하도록 지시하는 것으로 판매합니다.프로젝트 컴파일 옵션에 BUILD_DLL을 추가해야 하며 프로젝트 고유의 이름으로 이름을 변경할 수 있습니다(dll이 dll을 사용하는 경우).

또한 함수 이름을 변경하고 해독을 해제하기 위해 .def 파일을 만들어야 할 수도 있습니다(C/C++는 이러한 이름을 망함).이 블로그 엔트리는 흥미로운 출발점이 될 수 있습니다.

커스텀 dll을 로드하는 것은 시스템 dll을 로드하는 것과 같습니다.DLL이 시스템 경로에 있는지 확인하십시오.C:\windows\ 또는 어플리케이션의 현용 dir는 dll을 넣기 쉬운 장소입니다.

C++ dls를 쓸 때 주의해야 할 것은 이름 망치기입니다.C와 C++ 간의 상호 운용성을 원한다면 dll 내에서 비혼합형 C-스타일 함수를 내보내는 것이 좋습니다.

dll을 사용하기 위한 두 가지 옵션이 있습니다.

  • lib 파일을 사용하여 기호를 연결 - 컴파일 시간 동적 연결
  • LoadLibrary()을 사용하여 포인터를 (「기능 포인터」).GetProcAddress linking 이라고 고고부부부부다다런타임 다이내믹 링크

그러나 두 번째 방법을 사용하면 클래스를 내보낼 수 없습니다.

VB6의 경우:

C 함수를 __stdcall로 선언해야 합니다.그렇지 않으면 "invalid calling convention" 유형의 오류가 발생합니다.기타 질문 사항:

VB 프런트 엔드에서 포인터/레퍼런스로 인수를 받을 수 있습니까?

예, ByRef/ByVal 수식자를 사용합니다.

DLL은 프론트 엔드의 이론 함수를 호출할 수 있습니까?

예, Address Of 문을 사용합니다.이전에 함수 포인터를 dll로 전달해야 합니다.

또는 기능 포인터를 VB에서 가져와 호출할 수 있는지조차 알 수 없습니다.

예, Address Of 문을 사용합니다.

업데이트(더 많은 질문이 표시됨:

VB에 로드하려면 일반적인 메서드(winsock.ocx 또는 기타 런타임 로드 시 수행할 작업, 대신 DLL을 찾기 위해 수행할 작업)를 수행합니까?아니면 모듈에 API 콜을 넣어야 합니까?

다음과 같이 VB6 코드에서 디셀러 API 함수를 사용해야 합니다.

Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
   (ByVal hwndOwner As Long, _
    ByVal nFolder As Long, _
    ByRef pidl As Long) As Long

언급URL : https://stackoverflow.com/questions/847396/compile-a-dll-in-c-c-then-call-it-from-another-program

반응형