I recently developed a small program that needs to use FFT, but there is no reliable FFT code in C #, and the speed is not satisfactory. I found that MIT has done a good C ++ class library (http://www.fftw.org/) can better solve the problem of FFT and the computation speed is known as the world's fastest (although not verified, but indeed very fast ). So we studied calling the dll of C ++ in C.
1. to call C ++ in C #, you must first package the methods in C ++ into the methods in C #. The following is not what I wrote, but it is all about the process, "libfftw3-3.dll" file name, "fftw_malloc" c ++ function name, other parameters can be selected with reference to the help of. Remember using System. Runtime. InteropServices. The encapsulated method must be static. You don't need to talk about how to use static functions.
1 /// <summary>
2 // Contains the Basic Interface FFTW functions for double-precision (double) operations
3 /// </summary>
4 public class FFT
5 {
6 /// <summary>
7 // Allocates FFTW-optimized unmanaged memory
8 /// </summary>
9 // <param name = "length"> Amount to allocate, in bytes </param>
10 /// <returns> Pointer to allocated memory </returns>
11 [DllImport ("libfftw3-3.dll ",
12 EntryPoint = "fftw_malloc ",
13 ExactSpelling = true,
14 CallingConvention = CallingConvention. Cdecl)]
15 public static extern IntPtr malloc (int length );
16}
2. Next to the key question, how can we set the parameters? C ++ uses a large number of pointers without pointers in C. Don't worry. Have you seen the IntPtr (using System) in the previous example and the function return value? In fact, this is the address data type in C. Simple data types (such as int) can be directly used in the call, and a few (such as string) are easy to handle specially. For complex data types (classes, array ...) this IntPtr will be used.
For C ++, all types of pointers are replaced by IntPtr in C #. How can this problem be solved? Here we also involve a proxy GCHandle (using System. Runtime. InteropServices) that can help us convert between addresses and objects. I will give an example.
1 IntPtr plan;
2
3 double [] fin = new double [nx * ny * 2];
4 GCHandle hin = GCHandle. Alloc (fin, GCHandleType. Pinned );
5
6 plan = FFT. dft_2d (nx, ny, hin. AddrOfPinnedObject (), hin. AddrOfPinnedObject (), fftw_direction.Forward, fftw_flags.Estimate );
Dft_2d prototype: The following two parameters are enumeration types.
1 public static extern IntPtr dft_2d (int nx, int ny, IntPtr input, IntPtr output, fftw_direction direction, fftw_flags flags );
FFT. dft_2d is the encapsulated target function. We want to call this function. Fin is a complex object, hin Is Our proxy, Alloc operation is to bind the object and memory to the system proxy. Hin. addrOfPinnedObject () is the IP address corresponding to the fin (IntPtr type). We pass it as a pointer to C ++, in this way, C ++ will call fin data, and if C ++ modifies the data of the hin proxy in the function C #, the data will also change, C ++ users are familiar with this method of getting output results by passing in pointers. GCHandle also has an important attribute Target. in C #, you can directly obtain the proxy object through this attribute, so that we can change the object pointer or change the pointer to an object.
Simply put, 1. bind an object through GCHandle hin = GCHandle. Alloc (fin, GCHandleType. Pinned) and use hin. AddrOfPinnedObject () to obtain the IntPtr address for C ++.
2. Get the object to C # using hin. Target
Note: 1. alloc has bound the object to the memory. If you modify the fin object later, for example, adding fin = new double [2] to the fifth line, there is no impact on hin, therefore, the value assignment operation must be executed before Alloc. Remember to assign an initial value to the bound object. Otherwise, C ++ will report a null pointer (new is not very tiring !).
3 is it easy, but I still need to say a few more words. Since C ++ and proxy are used, do not forget to release the memory. C # programmers can easily forget this. C ++ class libraries generally provide release methods. GCHandle has a Free () function. Remember this !!!
From Ghost_zhao