digitalmars.D - extern export (Pascal) does not works correctly under Windows platform
- Andrey (112/112) Feb 15 2013 I've been created C# console app by MS VS2008 and shared library
- Andrej Mitrovic (8/10) Feb 15 2013 No it's not, pascal parameters are pushed left-to-right, stdcall does
mydll.dll by D dmd tool. mydll consist of: dll.d, mydll.d, mydll.def. compiled by command: dmd -ofmydll.dll mydll.d dll.d mydll.def ------- dll.d code here: module WWWW; version(Windows) { import std.c.windows.windows; import core.sys.windows.dll; __gshared HINSTANCE g_hInst; extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: g_hInst = hInstance; dll_process_attach( hInstance, true ); break; case DLL_PROCESS_DETACH: dll_process_detach( hInstance, true ); break; case DLL_THREAD_ATTACH: dll_thread_attach( true, true ); break; case DLL_THREAD_DETACH: dll_thread_detach( true, true ); break; default: break; } return true; } } -------- mydll.d code here: module mydll; import std.stdio; import WWWW; // pascal model is the same that stdcall export extern(Pascal) // full analog of STDCALL { void dllprint() // works correctly everytime { writeln("Hello!!!"); } void dllprint_vec(byte* pBytes, uint len) // the second parameter always wrong!!! { writefln("lengths=%d", len); writeln("Bytes are:"); for(int i=0; i<len; i++) writefln("%d", pBytes[i]); } void printlength(uint len, double d) // the second parameter always wrong!!! { writefln("sizeof(uint)=%d, printlength=%d, d = %.2f \n", typeof(len).sizeof, len, d); } } ---------mydll.def LIBRARY "mydll.dll" EXETYPE NT SUBSYSTEM WINDOWS CODE PRELOAD DISCARDABLE DATA PRELOAD SINGLE EXPORTS --------------------------- namespace Test_D_DLL { public partial class Form1 : Form { [DllImport("mydll.dll", CallingConvention = CallingConvention.StdCall)] public static unsafe extern void DLLPRINT(); [DllImport("mydll.dll", CallingConvention = CallingConvention.StdCall)] public static unsafe extern void DLLPRINT_VEC(byte[] pB, uint len); [DllImport("mydll.dll", CallingConvention = CallingConvention.StdCall)] public static unsafe extern void PRINTLENGTH(uint len, double d); unsafe public Form1() { InitializeComponent(); dllprint(); // is OK, prints "Hello!" uint d = 89898989; printlength(d, 0.7612); // WRONG!!! the second argument prints always 0.0, but expects 0.7612 !!!! byte[] b = new byte[5]; b[0] = 123; b[1] = 10; b[2] = 20; b[3] = 30; b[4] = 88; Console.WriteLine(sizeof(uint)); d = 5; fixed (byte* pB = &(b[0])) { DLLPRINT_VEC(pB, d); // FATAL EXCEPTION!!! the second parameter more bigger than 5!!! } } } } You can find this DMD bug in 2.58 version, 2.59, 2.60, 2.61. Why??? And how can we solve this problem???
Feb 15 2013
On 2/15/13, Andrey <vangelisforever yandex.ru> wrote:// pascal model is the same that stdcall export extern(Pascal) // full analog of STDCALLNo it's not, pascal parameters are pushed left-to-right, stdcall does it the other way around. Try using extern(Windows) here and see if that works. See http://en.wikipedia.org/wiki/X86_calling_conventions#pascal and http://en.wikipedia.org/wiki/X86_calling_conventions#stdcall . Also see Agner's detailed calling convention PDF: www.agner.org/optimize/calling_conventions.pdf
Feb 15 2013