6.2 C# Accessing C99 SDK
Overview
C# applications can call C99 SDK dynamic library via DllImport (P/Invoke) for cross-language integration.
6.2.1 Prerequisites
| Dependency | Description |
|---|---|
| .NET | Framework 4.5+ or .NET Core 3.1+ |
| C99 SDK | c_arm_api.dll (Windows) |
6.2.2 Minimal Example: Connect and Disconnect
csharp
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("c_arm_api.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr Arm_Create();
[DllImport("c_arm_api.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Arm_Destroy(IntPtr handle);
[DllImport("c_arm_api.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Arm_Connect(IntPtr handle, string controllerIp, string teachPanelIp);
[DllImport("c_arm_api.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Arm_Disconnect(IntPtr handle);
static void Main(string[] args)
{
// Create handle
IntPtr handle = Arm_Create();
// Connect to robot
int ret = Arm_Connect(handle, "10.27.1.2", "10.27.1.102");
Console.WriteLine($"Connect result: {ret}");
// Disconnect
Arm_Disconnect(handle);
// Destroy handle
Arm_Destroy(handle);
Console.WriteLine("Done");
}
}6.2.3 Object-Oriented Wrapper (Facade Pattern)
You can create an Arm class that wraps C99 functions into a C# object-oriented API:
csharp
using System;
using System.Runtime.InteropServices;
public class Arm : IDisposable
{
private const string DllName = "c_arm_api.dll";
private IntPtr _handle;
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr Arm_Create();
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Arm_Destroy(IntPtr handle);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern int Arm_Connect(IntPtr handle, string controllerIp, string teachPanelIp);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
private static extern void Arm_Disconnect(IntPtr handle);
public void Connect(string controllerIp, string teachPanelIp = null)
{
if (_handle == IntPtr.Zero)
_handle = Arm_Create();
int ret = Arm_Connect(_handle, controllerIp, teachPanelIp);
if (ret != 0)
throw new InvalidOperationException($"Connect failed: {ret}");
}
public void Disconnect()
{
if (_handle != IntPtr.Zero)
Arm_Disconnect(_handle);
}
public void Dispose()
{
Disconnect();
if (_handle != IntPtr.Zero)
{
Arm_Destroy(_handle);
_handle = IntPtr.Zero;
}
}
}
// Usage example
using (var arm = new Arm())
{
arm.Connect("10.27.1.2", "10.27.1.102");
Console.WriteLine("Connected successfully");
}6.2.4 Notes
- Calling Convention: C99 SDK uses
cdecl, must specifyCallingConvention = CallingConvention.Cdecl - Platform Target: Ensure C# project platform target matches DLL (x64)
- DLL Path: Ensure DLL is in searchable path
- Thread Safety: Same handle cannot be accessed concurrently across threads
- BasScript Builder: C99 now exposes
ArmBasScriptHandleandArmBasExtraParamHandle, which are more suitable for C# object wrappers than manually assembling BAS script text arrays - Builder Convenience Wrappers:
Arm_BasScript_SetName/AppendLine(s)andArm_BasValue_*map naturally to C# instance methods and static factories, reducing manualArmBasValueassembly