programing

C#에서 C 함수를 호출할 수 있습니까?그물

prostudy 2022. 8. 7. 16:13
반응형

C#에서 C 함수를 호출할 수 있습니까?그물

Clib가 있고 이 라이브러리의 함수를 C# 어플리케이션에서 호출하고 싶습니다.Clib 파일을 링커 입력으로 추가하고 소스 파일을 추가 종속성으로 추가하여 Clib에 C++/CLI 래퍼 작성을 시도했습니다.

C 출력을 c# 어플리케이션에 추가하는 방법을 잘 모르기 때문에 이를 실현하는 더 좋은 방법이 있습니까?

마이 C 코드 -

__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
                            unsigned char * publicKey,
                            unsigned char   publicKeyLen);

My CPP 래퍼 -

long MyClass::ConnectSessionWrapper(unsigned long handle,
                                unsigned char * publicKey,
                                unsigned char   publicKeyLen)
    {
        return ConnectSession(handle, publicKey, publicKeyLen);
    }

예를 들어 Linux의 경우 다음과 같습니다.

) 1) 을 합니다.C 파일,libtest.c다음 내용을 포함합니다.

#include <stdio.h>

void print(const char *message)
{
  printf("%s\\n", message);
}

printf의 어떤 것이든 수 있어요.C호출할 라이브러리에서 기능을 수행합니다.「 」가 C++을 넣는 마세요C이름을 더럽히지 않기 위해서요.

② 성)를C#

using System;

using System.Runtime.InteropServices;

public class Tester
{
        [DllImport("libtest.so", EntryPoint="print")]

        static extern void print(string message);

        public static void Main(string[] args)
        {

                print("Hello World C# => C++");
        }
}

3).so 가 "/usr 와 표준 한 3) "/usr/lib" 의 libtest 가 될 수 .소우so을 /.DllNotFoundException libtest.so libtest.so / usr / lib 이로이 CWD 。export LD_LIBRARY_PATH=pwd

여기서부터의 크레딧

편집

Windows 의 경우는, 큰 차이가 없습니다.여기서 를 들자면, 당신은 당신의 코드에 동봉만 하면 됩니다.*.cpp당신의 extern "C" 같은 거

extern "C"
{
//Note: must use __declspec(dllexport) to make (export) methods as 'public'
      __declspec(dllexport) void DoSomethingInC(unsigned short int ExampleParam, unsigned char AnotherExampleParam)
      {
            printf("You called method DoSomethingInC(), You passed in %d and %c\n\r", ExampleParam, AnotherExampleParam);
      }
}//End 'extern "C"' to prevent name mangling

그런 다음 컴파일을 하고 C# 파일에서 다음을 수행합니다.

[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]

public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);

그 다음 그것을 사용합니다.

using System;

    using System.Runtime.InteropServices;

    public class Tester
    {
            [DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]

    public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);

            public static void Main(string[] args)
            {
                    ushort var1 = 2;
                    char var2 = '';  
                    DoSomethingInC(var1, var2);
            }
    }

UPDATE - 2019년 2월 22일 : 이 답변은 많은 표가 쇄신되고 있기 때문에 C 메서드라고 하는 더 나은 방법으로 업데이트하기로 했습니다.이전에 사용하라고 제안했습니다.unsafe은, 「」를 하는 것입니다.MarshalAs을 변환하기 위한 입니다. 물 netstring a까지char*또한 VS2017에서는 Win32 프로젝트가 없어지기 때문에 Visual C++ dll 또는 빈 프로젝트를 생성하여 수정해야 합니다.★★★★★★★★★★★★★★★★★★!

P/Invoke C# C는 C/Invoke C입니다.
C dll C # lbrary 작음 。

  1. 새로운 C# 라이브러리 프로젝트 작성 ('Wrapper'라고 부릅니다)
  2. 솔루션에 Win32 프로젝트를 추가하고 응용 프로그램 유형을 DLL로 설정합니다(CLIBRARY라고 부릅니다).

    • 다른 모든 cpp/h 파일은 필요 없기 때문에 삭제할 수 있습니다.
    • CLibrary.cpp 파일의 이름을 CLibrary.c로 변경합니다.
    • CLibrary.h 헤더 파일 추가
  3. 이제 CLibrary 프로젝트를 구성하고 마우스 오른쪽 버튼을 클릭하여 속성으로 이동한 후 구성: "모든 구성"을 선택해야 합니다.

    • [ Configuration Properties ]> [ C / C + + ]> [ Precompiled Headers ]에서 [Not using Precompiled Headers]를 설정합니다.
    • 같은 C/C++ 브랜치로 [Advanced](상세설정)으로 이동하여 [C코드(/TC)로 컴파일]를 변경합니다.
    • 다음으로 [Linker]브런치에서 [General]으로 이동하여 [Output File]를 [$(SolutionDir)]으로 변경합니다.Wrapper\$(프로젝트명).dll" 그러면 빌드된 C DLL이 C# 프로젝트 루트에 복사됩니다.

클라이브리.h

__declspec(dllexport) unsigned long ConnectSession(unsigned long   handle,
                                                   unsigned char * publicKey,
                                                   unsigned char   publicKeyLen);

클라이버러리

#include "CLibrary.h"

unsigned long ConnectSession(unsigned long   handle,
                             unsigned char * publicKey,
                             unsigned char   publicKeyLen)
{
    return 42;
}
  • CLibrary 프로젝트를 오른쪽 클릭하여 빌드하면 C# 프로젝트 디렉토리에 DLL이 표시됩니다.
  • C# Wrapper 프로젝트를 오른쪽 클릭하여 기존 아이템을 추가하고 CLibrary.dll을 추가합니다.
  • CLibrary.dll을 클릭하고 속성 페인으로 이동하여 "Copy to output Directory"를 "Copy Always"로 설정합니다.

Wrapper 프로젝트는 CLibrary에 의존하도록 하는 것이 좋습니다.CLibrary는 Wrapper 프로젝트를 우클릭하여 "Project Dependencies"로 이동하고 "CLibrary"를 체크함으로써 구축할 수 있습니다.실제 래퍼 코드의 경우:

ConnectSessionWrapper.cs

using System.Runtime.InteropServices;

namespace Wrapper
{
    public class ConnectSessionWrapper
    {
        [DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint ConnectSession(uint handle,
            [MarshalAs(UnmanagedType.LPStr)] string publicKey,
            char publicKeyLen);

        public uint GetConnectSession(uint handle, 
                                      string publicKey,
                                      char publicKeyLen)
        {
            return ConnectSession(handle, publicKey, publicKeyLen);
        }
    }
}

전화나 해GetConnectSession, 그리고 그것은 다시 돌아올 것이다.42.

결과:
콘솔 응용 프로그램에서 래퍼 라이브러리 테스트

네, VS 2010을 열고 Goto File -> New -> Project -> Visual C++ -> Win32 -> Win32 Project에 이름을 붙입니다( 경우는 HelloWorldDll) 다음 창에서 [DLL]를 선택하고 [Project]선택합니다.

[ Solution Explorer ]탭은 보통 VS 창의 오른쪽에서 오른쪽 버튼을 클릭하여 [Source Files]-> [ Add Item ]-> [ C+ + file ( . cpp ) ]를 오른쪽 클릭하여 이름을 지정합니다(내 경우는 [Hello World ] ) 。

그런 다음 새 클래스에 이 코드를 붙여넣습니다.

#include <stdio.h>

extern "C"
{
  __declspec(dllexport) void DisplayHelloFromDLL()
  {
    printf ("Hello from DLL !\n");
  }
}

이제 프로젝트를 빌드합니다.프로젝트 DEBUG 폴더로 이동하면 다음 항목이 나타납니다.Hello World Dll.dll.

이제 dll에 액세스하는 C# 어플리케이션을 만듭니다.Goto File -> New -> Project -> Visual C# -> Console Application에 이름(CallDllCSharp)을 붙입니다.다음 코드를 복사하여 메인에 붙여넣습니다.

using System;
using System.Runtime.InteropServices;
...
        static void Main(string[] args)
        {
            Console.WriteLine("This is C# program");
            DisplayHelloFromDLL();
            Console.ReadKey();
        }

프로그램을 빌드합니다.이제 두 앱이 모두 구축되었으므로 이를 사용하여 *.discs와 .exe(bin/discs/.exe)를 같은 디렉토리에 저장하고 응용 프로그램 출력을 실행합니다.

이것은 C# 프로그램입니다.

DLL에서 헬로!

이것으로 당신의 문제가 해결되기를 바랍니다.

참고 자료:

메모: 다음 코드는 DLL로부터의 여러 메서드에 대한 것입니다.

[DllImport("MyLibc.so")] public static extern bool MyLib_GetName();
[DllImport("MyLibc.so")] public static extern bool MyLib_SetName(string name);
[DllImport("MyLibc.so")] public static extern bool MyLib_DisplayName(string name);

public static void Main(string[] args)
{
string name = MyLib_GetName();
MyLib_SetName(name);
MyLib_DisplayName(name);
}

P/Invoke 메서드는 지금까지 광범위하고 반복적으로 설명되어 왔습니다.여기서 놓치고 있는 것은 C++/CLI 방식에는 큰 이점이 있다는 것입니다.안전요청을 합니다.C 함수의 콜이 하늘을 향해 블라인드를 쏘는 것과 같은 P/Invoke와는 대조적으로(이 비교가 허가되어 있는 경우), C 함수를 호출할 때 함수 인수를 체크하는 사람은 없습니다.이 경우 C++/CLI를 사용하면 일반적으로 사용할 함수 프로토타입이 포함된 헤더 파일을 포함할 수 있습니다.잘못된 인수/많은 인수/거의 인수를 사용하여 C 함수를 호출하는 경우 컴파일러는 이를 알려줍니다.

일반적으로 어느 쪽이 좋은지 말할 수 없다고 생각합니다만, 솔직히 어느 쪽도 마음에 들지 않습니다.

언급URL : https://stackoverflow.com/questions/11425202/is-it-possible-to-call-a-c-function-from-c-net

반응형