É possível chamar uma function C de c # .net

Eu tenho um lib C e quer chamar a function nesta biblioteca do aplicativo c #. Eu tentei criar um wrapper C ++ / CLI no C lib adicionando o arquivo C lib como input do vinculador e adicionando os arquivos de origem como dependencies adicionais.

Existe alguma maneira melhor de conseguir isso, como não tenho certeza de como adicionar saída C para o aplicativo c #.

Meu código C –

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

Meu CPP Wrapper –

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

O exemplo será, para o Linux :

1) Crie um arquivo C , libtest.c com este conteúdo:

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

Esse é um simples pseudo-wrapper para printf. Mas representa qualquer function C na biblioteca que você deseja chamar. Se você tem uma function C++ , não esqueça de colocar extern C para evitar o nome.

2) crie o arquivo 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) A menos que você tenha a biblioteca libtest.so em um caminho de biblioteca padrão como “/ usr / lib”, é provável que você veja um System.DllNotFoundException, para corrigir isso você pode mover seu libtest.so para / usr / lib, ou melhor ainda, basta adicionar seu CWD ao caminho da biblioteca: export LD_LIBRARY_PATH=pwd

créditos daqui

EDITAR

Para o Windows , não é muito diferente. Tomando um exemplo a partir daqui , você só tem que include no seu arquivo *.cpp seu método com o extern "C" Algo como

 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 

então, compile e no seu arquivo C #

 [DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")] public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam); 

e depois é só usá-lo:

 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); } } 

Você pode chamar diretamente funções C de C # usando P / Invoke.
Aqui está um pequeno how-to sobre como criar um lbrary C # que envolve uma dll C.

  1. Criar um novo projeto de biblioteca C # (eu chamarei de “Wrapper”)
  2. Adicione um projeto Win32 à solução, defina o tipo de aplicativo como: DLL (eu chamarei de “CLibrary”)

    • Você pode remover todos os outros arquivos cpp / h, já que não precisaremos deles
    • Renomeie o arquivo CLibrary.cpp para CLibrary.c
    • Adicione um arquivo de header CLibrary.h
  3. Agora precisamos configurar o projeto CLibrary, clicar com o botão direito do mouse e ir para propriedades, e selecionar Configuration: “All Configurations”

    • Nas propriedades de configuração> C / C ++> headers pré-compilados, defina headers pré-compilados para: “não usando headers pré-compilados”
    • Na mesma ramificação C / C ++, vá para Advanced, altere Compile As para: “Compile as code C (/ TC)”
    • Agora, na ramificação do Linker, vá para Geral e altere o Arquivo de Saída para: “$ (SolutionDir) Wrapper \ $ (ProjectName) .dll”, isso copiará a DLL C construída para a raiz do projeto C #.

CLibrary.h

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

CLibrary.c

 #include "CLibrary.h" unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen) { return 42; } 
  • Clique com o botão direito do mouse no projeto CLibrary, construa-o, para obtermos a DLL no diretório do projeto C #
  • Clique com o botão direito do mouse no projeto C # Wrapper, adicione um item existente, adicione CLibrary.dll
  • Clique em CLibrary.dll, vá para o painel de propriedades, defina “Copiar para o diretório de saída” para “Copiar sempre”

É uma boa ideia tornar o projeto Wrapper dependente do CLibrary para que o CLibrary seja construído primeiro, você pode fazer isso clicando com o botão direito do mouse no projeto Wrapper, indo para “Dependências do Projeto” e verificando “CLibrary”. Agora, para o código do wrapper real:

ConnectSessionWrapper.cs

 using System; using System.Runtime.InteropServices; namespace Wrapper { public class ConnectSessionWrapper { [DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)] unsafe static extern UInt32 ConnectSession(UInt32 handle, char* publicKey, char publicKeyLen); public unsafe UInt32 GetConnectSession(UInt32 handle, string publicKey, char publicKeyLen) { //"Convert" string to char* char* pubKey; fixed (char* bptr = publicKey) { pubKey = (char*)bptr; } return ConnectSession(handle, pubKey, publicKeyLen); } } } 
  • A última coisa que você precisa fazer é clicar com o botão direito do mouse no projeto Wrapper, definir Configuração como “Todas as configurações” e marcar Permitir código não seguro .
    A única razão para usar código não seguro é porque você tinha um char * como parâmetro e precisávamos converter uma string para um ponteiro fixo de char.

Resultado:
Testando a biblioteca do wrapper em um aplicativo de console

Ok bem, Open VS 2010, Goto Arquivo -> Novo -> Projeto -> Visual C ++ -> Win32 -> Projeto Win32 e dar-lhe um nome (HelloWorldDll no meu caso), Em seguida, na janela que se segue em Application Type escolha ‘DLL ‘ e sob Opções Adicionais, escolha ‘ Projeto Vazio ‘ .

Agora vá para a aba Solution Explorer, geralmente à direita da janela do VS, clique com o botão direito em Source Files -> Add Item -> arquivo C ++ (.cpp) e dê a ele um nome (HelloWorld no meu caso)

Então, na nova class, cole este código:

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

Agora, construa o projeto, depois de navegar para a pasta DEBUG de seus projetos e lá você deve encontrar: HelloWorldDll.dll .

Agora, vamos criar nosso aplicativo C # que acessará a dll, Ir Arquivo -> Novo -> Projeto -> Visual C # -> Aplicativo de Console e dar a ele um nome (CallDllCSharp), agora copie e cole este código no seu principal:

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

e construir o programa, agora que temos ambos os nossos aplicativos construídos permite usá-los, obter o seu * .dll e seu exe (bin / debug / .exe) no mesmo diretório, e executar a saída do aplicativo deve ser

Este é o programa C #

Olá da DLL!

Espero que isso elimine alguns dos seus problemas.

Referências :

  • Como criar uma biblioteca DLL em C e, em seguida, usá-lo com c #