Por que o C# não vive no vácuo e como isso funciona
\n\nQuando comecei a trabalhar com C# há cerca de dez anos, parecia-me que o .NET era um universo autossuficiente. Bibliotecas, frameworks, bancos de dados — tudo à mão. Mas então surgiu uma tarefa: precisava usar uma biblioteca C++ antiga para processamento de sinais. E foi aí que entendi — a integração C# com outras linguagens não é um luxo, mas uma necessidade para qualquer projeto sério.
\n\nHoje, o C# é uma linguagem multiplataforma com um ecossistema rico, mas não consegue fazer tudo. Às vezes é preciso executar um script Python para machine learning, outras vezes chamar uma função nativa do Rust para máxima performance, e às vezes incorporar um motor JavaScript para geração dinâmica de UI. A boa notícia: o C# consegue se integrar praticamente com todas.
\n\nNeste artigo, mostrarei cenários reais de interação do C# com outras linguagens com código funcional, benchmarks e armadilhas. Vamos lá!
\n\nP/Invoke: o clássico para C e C++
\n\nPlatform Invocation Services (P/Invoke) é um mecanismo nativo do .NET para chamar funções de DLLs nativas. Ele existe desde a primeira versão do .NET e continua sendo a forma mais rápida de integração com código C/C++.
\n\nExemplo básico: chamar uma função do C
\n\nSuponha que temos uma biblioteca nativa math_helper.dll com a função:
// math_helper.h\nextern "C" __declspec(dllexport) double calculate_power(double base, int exp);\n\nNo C#, conectamos assim:
\n\nusing System.Runtime.InteropServices;\n\npublic class NativeMath\n{\n [DllImport("math_helper.dll", CallingConvention = CallingConvention.Cdecl)]\n public static extern double calculate_power(double base, int exp);\n}\n\n// Uso\ndouble result = NativeMath.calculate_power(2.0, 10);\nConsole.WriteLine($"2^10 = {result}"); // 1024\n\nPontos importantes ao usar P/Invoke C#:
\n- \n
- Sempre especifique
CallingConvention— na maioria das vezesCdeclouStdCall. \n - Para strings, use
MarshalAs(UnmanagedType.LPStr)ouLPWStr. \n - Passe estruturas por referência usando
refouout. \n
O P/Invoke tem uma sobrecarga mínima — literalmente alguns nanossegundos por chamada. Se você precisa integrar C# com C++ para cálculos de alto desempenho, esta é a sua escolha.
\n\nC++/CLI: a ponte entre mundos
\n\nC++/CLI é uma extensão do Visual C++ que permite escrever código que funciona tanto em ambiente gerenciado (.NET) quanto não gerenciado. Não é uma linguagem separada, mas um híbrido frequentemente usado para criar wrappers em torno de bibliotecas C++.
\n\nExemplo de wrapper para OpenCV
\n\nSuponha que temos uma função C++ que processa imagens:
\n\n// NativeImageProcessor.h\n#pragma once\npublic ref class ImageProcessor\n{\npublic:\n static System::Drawing::Bitmap^ ApplyFilter(System::Drawing::Bitmap^ bmp);\n};\n\nInternamente, chamamos o OpenCV nativo e, externamente, retornamos um Bitmap gerenciado. No C#, usamos como uma biblioteca .NET comum:
using ImageProcessorLib;\n\nvar img = new Bitmap("photo.jpg");\nvar processed = ImageProcessor.ApplyFilter(img);\nprocessed.Save("filtered.jpg");\n\nA integração C++/CLI oferece controle total sobre a memória e evita marshaling. A desvantagem é que o código se torna dependente de plataforma e mais difícil de depurar.
\n\nPython.NET: chamando Python do C#
\n\nPython é o rei da Ciência de Dados e machine learning. E se o seu projeto em C# exigir, por exemplo, executar uma rede neural no PyTorch ou processar texto com spaCy, chamar Python do C# via Python.NET é o que você precisa.
\n\nInstalação e primeiro exemplo
\n\nInstalamos o pacote:
\n\ndotnet add package Python.Runtime.NETStandardBlogs
Book Recommendations
Leia também