تكامل C# مع اللغات الأخرى: من P/Invoke إلى Python وJavaScript

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا لا يعيش C# في فراغ، وكيف يعمل ذلك

\n\n

عندما بدأت العمل مع C# منذ حوالي عشر سنوات، كنت أعتقد أن .NET هو كون مكتفٍ ذاتيًا. المكتبات، الأطر، قواعد البيانات - كل شيء في متناول اليد. ولكن بعد ذلك جاءت مهمة: كنت بحاجة لاستخدام مكتبة C++ قديمة لمعالجة الإشارات. وهنا أدركت - تكامل C# مع اللغات الأخرى ليس ترفًا، بل ضرورة لأي مشروع جاد.

\n\n

اليوم، C# هي لغة متعددة المنصات مع نظام بيئي غني، لكنها لا تستطيع فعل كل شيء. أحيانًا تحتاج لتشغيل سكريبت Python للتعلم الآلي، وأحيانًا لاستدعاء دالة أصلية من Rust لتحقيق أقصى أداء، وأحيانًا لتضمين محرك JavaScript لتوليد واجهة مستخدم ديناميكية. الخبر السار: C# يمكنه التعامل مع الجميع تقريبًا.

\n\n

في هذه المقالة، سأعرض سيناريوهات حقيقية لـ تفاعل C# مع اللغات الأخرى مع كود عملي، معايير أداء، والمزالق المحتملة. هيا بنا!

\n\n

P/Invoke: الكلاسيكي لـ C وC++

\n\n

Platform Invocation Services (P/Invoke) هي آلية مدمجة في .NET لاستدعاء الدوال من مكتبات DLL الأصلية. ظهرت منذ الإصدار الأول من .NET ولا تزال أسرع طريقة للتكامل مع كود C/C++.

\n\n

مثال أساسي: استدعاء دالة من C

\n\n

لنفترض أن لدينا مكتبة أصلية math_helper.dll تحتوي على دالة:

\n\n
// math_helper.h\nextern "C" __declspec(dllexport) double calculate_power(double base, int exp);
\n\n

في C# نربطها كالتالي:

\n\n
using 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// الاستخدام\ndouble result = NativeMath.calculate_power(2.0, 10);\nConsole.WriteLine($"2^10 = {result}"); // 1024
\n\n

نقاط مهمة عند P/Invoke C#:

\n
    \n
  • حدد دائمًا CallingConvention - غالبًا Cdecl أو StdCall.
  • \n
  • للسلاسل النصية استخدم MarshalAs(UnmanagedType.LPStr) أو LPWStr.
  • \n
  • مرر الهياكل بالمرجع عبر ref أو out.
  • \n
\n\n

P/Invoke يعطي تكاليف إضافية ضئيلة - حرفيًا بضع نانوثانية لكل استدعاء. إذا كنت بحاجة إلى دمج C# مع C++ للحسابات عالية التحميل - فهذا هو اختيارك.

\n\n

C++/CLI: جسر بين العوالم

\n\n

C++/CLI هو امتداد لـ Visual C++ يسمح بكتابة كود يعمل في كل من البيئة المُدارة (.NET) والبيئة غير المُدارة. إنها ليست لغة منفصلة، بل هجين يُستخدم غالبًا لإنشاء أغلفة لمكتبات C++.

\n\n

مثال غلاف لـ OpenCV

\n\n

لنفترض أن لدينا دالة C++ تعالج الصورة:

\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\n

داخليًا نستدعي OpenCV الأصلي، ونخرج Bitmap مُدارًا. من C# نستخدمها كمكتبة .NET عادية:

\n\n
using ImageProcessorLib;\n\nvar img = new Bitmap("photo.jpg");\nvar processed = ImageProcessor.ApplyFilter(img);\nprocessed.Save("filtered.jpg");
\n\n

تكامل C++/CLI يعطي تحكمًا كاملاً في الذاكرة ويتجنب المارشالينغ. العيب - يصبح الكود معتمدًا على المنصة وأكثر تعقيدًا في التصحيح.

\n\n

Python.NET: استدعاء Python من C#

\n\n

Python هو ملك علم البيانات والتعلم الآلي. وإذا كان مشروعك على C# يتطلب، على سبيل المثال، تشغيل شبكة عصبية على PyTorch أو معالجة نصوص عبر spaCy، فإن استدعاء Python من C# عبر Python.NET هو ما تحتاجه.

\n\n

التثبيت والمثال الأول

\n\n

نقوم بتثبيت الحزمة:

\n\n
dotnet add package Python.Runtime.NETStandard

المدونات

توصيات الكتب