articles » current » dot-net » call-an-external-function-using-dllimport

.NET: Call an External Function Using DllImport in C#

How to correctly use DllImport to call external functions in libraries on both windows (.dll files) and Linux (.so libraries).

When writing external functions for use by .NET, it may help to know which calling convention to use. Generally, use CallingConvention.StdCall which can be declared in Microsoft's Visual Studio C++ compiler by simply adding a __stdcall between the function return type and the function name. Also, make sure to declare the function an extern "C" function by wrapping it and others in a extern "C" { } block of code. This prevents the C++ compiler from mangling the name of the function up.

The IntPtr type is an interesting one. Use it for pointers to objects in memory, not primitive data types. A pointer to a pointer would be declared out IntPtr. There is an example of this below.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Runtime.InteropServices;
using System.Text;

namespace Code
	class FunctionImports
		// NOTE: STDCALL: The callee cleans the stack. The majority of Window API functions use this calling convention.
		[DllImport("kernel32", CallingConvention = CallingConvention.StdCall)]
		private static extern uint SetThreadExecutionState(uint esFlags);

		// NOTE: CDECL: The caller cleans the stack.This enables calling functions with variable arguments because the caller knows
		// how many were passed.This makes it appropriate to use methods that accept a variable number of parameters, like printf() does.
		[DllImport("prowaretech.dll", CallingConvention = CallingConvention.Cdecl)]
		private static extern uint SomeFunc(double[] floating_points);

		// NOTE: The name of the function as exported by the library is "UglyFuncName" and this
		// is a useful way to import a function while giving it a more descriptive name.
		[DllImport("prowaretech.dll", EntryPoint = "UglyFuncName", CallingConvention = CallingConvention.StdCall)]
		private static extern IntPtr PrettyFuncName(out IntPtr ppVar); // NOTE: a pointer to a pointer

		// NOTE: FASTCALL: FastCall is not supported! Use at one's own discretion!
		[DllImport("prowaretech.dll", CallingConvention = CallingConvention.FastCall)]
		private static extern void BasicFunc(string str);

		// NOTE: THISCALL: The first parameter is the "this" pointer and is stored in the ECX register. Other parameters
		// are pushed in the stack. This calling convention is used to call methods on classes from an unmanaged DLL.
		[DllImport("prowaretech.dll", CallingConvention = CallingConvention.ThisCall)]
		private static extern void BasicFuncOfAnObject(uint[] uint_array);

This site uses cookies. Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site. Read the privacy policy.