I am currently learning C++ (for eventually creating DLL's for Hooks). I have strengths in C# and would like to access the DLL's via pInvoke/DllImports.
I am using VS 2019 (and .NET Framework 4.7.2). As a sample for learning purposes, I have replicated the DLL as well as the C++ (console app) as described here: https://learn.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=vs-2019. This is working perfectly fine (as expected).
Now when I start trying to import the DLL into a C# Project I am running into problems (which I believe are DllImport related)
In the sample (c++) console app (which is working):
int main()
{
// Initialize a Fibonacci relation sequence.
fibonacci_init(1, 1);
// Write out the sequence values until overflow.
do {
std::cout << fibonacci_index() << ": " << fibonacci_current() << std::endl;
} while (fibonacci_next());
// Report count of values written before overflow.
std::cout << fibonacci_index() + 1 << " Fibonacci sequence values fit in an " << "unsigned 64-bit integer." << std::endl;
}
In the C# test console app (not working properly):
class Program
{
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void fibonacci_init(ulong a, ulong b);
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl))]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool fibonacci_next();
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern ulong fibonacci_current();
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern uint fibonacci_index();
static void Main(string[] args)
{
// Initialize a Fibonacci relation sequence.
fibonacci_init(1, 1);
// Write out the sequence values until overflow.
do {
Console.WriteLine($"{fibonacci_index()}: {fibonacci_current()}");
} while (fibonacci_next());
// Report count of values written before overflow.
Console.WriteLine($"{fibonacci_index() + 1} Fibonacci sequence values fit in an unsigned 64-bit integer.");
}
}
In the working (C++) app, the loop reaches 92 and prints
92: 12200160415121876738
and then exits the loop and prints 93 Fibonacci sequence values fit in an unsigned 64-bit integer.
However, in the failing (C#) app, it works up until the 92: 12200160415121876738
, but rather than exiting the loop, fabonacci_next()
continues to return true
and it keeps looping the line 92: 12200160415121876738
(no more increments, and never exits).
For the DllImport in C# I have tried both:
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl))]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool fibonacci_next();
and:
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl))]
public static extern bool fibonacci_next();
Same results either way. If someone could explain to me what I am doing wrong with the DllImport (causing it not to ever return true, when the same DLL works properly when linked to a C++ console app).
--- UPDATE ---
So the solution to the example above changing [return: MarshalAs(UnmanagedType.Bool)]
to [return: MarshalAs(UnmanagedType.I1)]
does work (with further important related information provided in the links given by GSerg in the comments below).
--- UPDATE 2 ---
(@David) I did intentionally (and incorrectly) leave out the exports as they were in the link I provided to the original DLL 'walkthrough' (my apologies). For completeness of the question the exports are:
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
extern "C" MATHLIBRARY_API void fibonacci_init(unsigned long long a, unsigned long long b);
extern "C" MATHLIBRARY_API bool fibonacci_next();
extern "C" MATHLIBRARY_API unsigned long long fibonacci_current();
extern "C" MATHLIBRARY_API unsigned fibonacci_index();