Click here to Skip to main content
15,891,939 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
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:
C++
#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;     // DLL support
namespace ConsoleApplication1
{
    class Program
    {
        [DllImport(&quot;testsub.dll&quot;)]
        static extern int addit(int a, int b);
        //public static extern void addit();
        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?
Posted
Updated 20-Feb-11 14:01pm
v6
Comments
Sandeep Mewara 16-Feb-11 1:36am    
Modified your question and directed it to all.

If the C code is 16 bit integer, and the C# is 32, then you need to use short instead of int in the C#:
C#
[DllImport("testsub.dll")]
static extern short addit(short a, short b);
You could also use Int16 - short is a synonym.
 
Share this answer
 
Comments
Yusuf 20-Feb-11 23:15pm    
Good catch, nice answer.
OriginalGriff is right. Make sure of the size of int by using sizeof(int) from you C code. Then use short if it returns 2, or int it it returns 4.

Additionnaly you may try using different calling conventions. For example:
C#
[DllImport("testsub.dll", CallingConvention=CallingConvention.StdCall)]
static extern short addit(short a, short b);
 
Share this answer
 
Answer 3 was on the right track, but it didn't work quite like that. Elsewhere I found that the following did work:

[System.Runtime.InteropServices.DllImport("testsub.dll",<br />
  CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]


And I used 'int' in C# and 'long' in C.

Thanks very much for your answers!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900