I've tried an example
here and got that to work, but it's of limited usefulness because it has no args and no return value, and the printf doesn't work. But I did get it to link and run without errors.
However when I try to add arguments and a return value, I get the error:
PInvokeStackImbalance was detected
Message: A call to PInvoke function 'ConsoleApplication1!ConsoleApplication1.Program::addit' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
I've looked all over the internet and so far haven't found any help as to what the problem is.
I'm using Visual C# Studio 2010 Express for C#, and www.codelite.org for the C compile. Could there be some kind of incompatibility?
If I do get it working, I'm planning to write up what I find about how to make DLLs work with various combinations and post it on the web to help others avoid stumbling where I've stumbled. DLLs have been around for so long, somebody must know the magic to get them to work.
More specifically, here's what I'm using:
#include <string.h>
#include <stdio.h>
extern "C"
{ __declspec(dllexport) int addit( int a, int b ); }
int addit (int a, int b) { return a+b;}
And here's the C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("testsub.dll")]
static extern int addit(int a, int b);
static void Main(string[] args)
{
int x = 2; int y = 3;
int answer = addit(x, y);
Console.WriteLine("hello world " + answer + "\n");
Console.WriteLine("another hello world" + x + "\n");
}
}
}
I also tried changing the 'int' to 'long' in the C code because int for C is 16 bits and int for C# is 32 bits, but that didn't make a difference.
P.S.: This is an extension to an article that I tried and thus a question to all. Article link is just a reference if someone needs to know.
------------------------------------
I don't know how to respond to the question without it seeming to be an answer, so I'll append it to the question:
I tried the suggested answer both ways:
1) C: int, C#: short (both should be 16-bits)
2) C: long, C#: int (both should be 32-bits)
Both result in the same error.
And sizeof() works only in C, and unless it runs, I don't have a way to print from C being as how it's a DLL. But everything I've read says that int is 16 bits, long is 32 bits.
Is it possible it's being compiled wrong: Here are the gcc commands:
gcc -c "C:/apk/adev/visual/testdlls/testsub.cpp" -g
-o ./Debug/testsub.o "-I." "-I."
gcc -shared -fPIC -o ./Debug/testsub.dll ./Debug/testsub.o "-L."
Also, I tried the DLL with a return value and no args and it works,
using option #1 above. So it looks like a problem with the arguments. I even tried just one argument and I got the same error.
I also tried the suggestion:
[DllImport("testsub.dll", CallingConvention=CallingConvention.StdCall)]
and it results in the same error.
--------------------------
[BTW, I don't know if this is where I should add additional info, I don't see a way to do a reply without having it appear to be an answer...]
No, Answers 1 and 3 didn't work. I tried the "callingconvention" idea. I think the C-long and C#-int are compatible because I can return a routine value with no args and it works, although I did try the int-and-short as suggested. It gets the error when I have even one simple argument.
I'm beginning to think that there's some fundamental incompatibility between Visual Studio C# 2010 Express and gcc. Perhaps M$ broke something from an earlier version that did work. But I typed one example from http://www.adp-gmbh.ch/win/misc/mingw/dll.html site directly and it gets the same error.
Any other ideas?