Jump to content
Sign in to follow this  
powderedtoastdude

DllCall with Parameters Fails

Recommended Posts

powderedtoastdude

Hi!

I'm puzzled by a DllCall problem. I've boiled it down to a simple test case which I'm attaching below. Basically: I have a trivial DLL that contains a function accepting an "int" parameter and returning an "int". When I call it with DllCall() but *don't* pass parameters to it, it succeeds. When I pass an int, it fails -- just terminates execution at call time with no apparent error.

Here's the test case code. Any help very much appreciated!

testcase.au3:

Dim Const $dllname = "testcase.dll"

$mainwindow = GUICreate("Test Case", 100, 100, 10, 10)
GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

$tcdll = DllOpen($dllname)
If (-1 = $tcdll) Then errorexit("Can't open " & $dllname)

ConsoleWrite("testing fn1" & @LF)
$lhs = DllCall($tcdll, "int", "fn1")
If (0 <> @error) Then errorexit("Calling fn1 results in error " & @error)
ConsoleWrite("fn1 returns " & $lhs[0] & @LF)

ConsoleWrite("testing fn2 with no input parameter" & @LF)
$lhs = DllCall($tcdll, "int", "fn2")
If (0 <> @error) Then errorexit("Calling fn2 results in error " & @error)
ConsoleWrite("fn2 returns " & $lhs[0] & @LF)

ConsoleWrite("testing fn2 with input parameter" & @LF)
$lhs = DllCall($tcdll, "int", "fn2", "int", 3)
If (0 <> @error) Then errorexit("Calling fn2 results in error " & @error)
ConsoleWrite("fn2 returns " & $lhs[0] & @LF)

DllClose($tcdll)
Exit

Func errorexit($msg)
    ConsoleWrite($msg & @LF)
    DllClose($tcdll)
    Exit
EndFunc

testcase.c:

#include <stdio.h>
#include <windows.h>
#include "testcase.h"

EXPORT int fn1() {
  return 42;
}

EXPORT int fn2(int n) {
  return 69 + n;
}

testcase.h:

#ifndef __TESTCASE_H
#define __TESTCASE_H

#ifdef __cplusplus
     #define cppfudge "C"
#else
     #define cppfudge
#endif

#ifdef BUILD_DLL
     // the dll exports
     #define EXPORT __declspec(dllexport)
#else
     // the exe imports
     #define EXPORT extern cppfudge __declspec(dllimport)
#endif

EXPORT int fn1();
EXPORT int fn2(int);

#endif

And of course the output:

>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "Z:\dev\elrapido\testcase.au3"    
testing fn1
fn1 returns 42
testing fn2 with no input parameter
fn2 returns 69
testing fn2 with input parameter
>Exit code: 0   Time: 0.334
Edited by powderedtoastdude

Share this post


Link to post
Share on other sites
martin

Hi!

I'm puzzled by a DllCall problem. I've boiled it down to a simple test case which I'm attaching below. Basically: I have a trivial DLL that contains a function accepting an "int" parameter and returning an "int". When I call it with DllCall() but *don't* pass parameters to it, it succeeds. When I pass an int, it fails -- just terminates execution at call time with no apparent error.

Here's the test case code. Any help very much appreciated!

testcase.au3:

Dim Const $dllname = "testcase.dll"

$mainwindow = GUICreate("Test Case", 100, 100, 10, 10)
GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

$tcdll = DllOpen($dllname)
If (-1 = $tcdll) Then errorexit("Can't open " & $dllname)

ConsoleWrite("testing fn1" & @LF)
$lhs = DllCall($tcdll, "int", "fn1")
If (0 <> @error) Then errorexit("Calling fn1 results in error " & @error)
ConsoleWrite("fn1 returns " & $lhs[0] & @LF)

ConsoleWrite("testing fn2 with no input parameter" & @LF)
$lhs = DllCall($tcdll, "int", "fn2")
If (0 <> @error) Then errorexit("Calling fn2 results in error " & @error)
ConsoleWrite("fn2 returns " & $lhs[0] & @LF)

ConsoleWrite("testing fn2 with input parameter" & @LF)
$lhs = DllCall($tcdll, "int", "fn2", "int", 3)
If (0 <> @error) Then errorexit("Calling fn2 results in error " & @error)
ConsoleWrite("fn2 returns " & $lhs[0] & @LF)

DllClose($tcdll)
Exit

Func errorexit($msg)
    ConsoleWrite($msg & @LF)
    DllClose($tcdll)
    Exit
EndFunc

testcase.c:

#include <stdio.h>
#include <windows.h>
#include "testcase.h"

EXPORT int fn1() {
  return 42;
}

EXPORT int fn2(int n) {
  return 69 + n;
}

testcase.h:

#ifndef __TESTCASE_H
#define __TESTCASE_H

#ifdef __cplusplus
     #define cppfudge "C"
#else
     #define cppfudge
#endif

#ifdef BUILD_DLL
     // the dll exports
     #define EXPORT __declspec(dllexport)
#else
     // the exe imports
     #define EXPORT extern cppfudge __declspec(dllimport)
#endif

EXPORT int fn1();
EXPORT int fn2(int);

#endif

And of course the output:

>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "Z:\dev\elrapido\testcase.au3"    
testing fn1
fn1 returns 42
testing fn2 with no input parameter
fn2 returns 69
testing fn2 with input parameter
>Exit code: 0   Time: 0.334

I know almost nothing about C++, but is it possible you need to use the "int:cdecl" as described in the help?

By default, AutoIt uses the 'stdcall' calling method. To use the 'cdecl' method place ':cdecl' after the return type.

DllCall("SQLite.dll", "int:cdecl", "sqlite3_open", "str", $sDatabase_Filename , "long_ptr", 0).


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
powderedtoastdude

I know almost nothing about C++, but is it possible you need to use the "int:cdecl" as described in the help?

Tried that... when I use "int:cdecl", for either the input parameter or the return value or both, I get @error = 2 (unknown return type). So I concluded that was the wrong thing to do.

Share this post


Link to post
Share on other sites
powderedtoastdude

Tried that... when I use "int:cdecl", for either the input parameter or the return value or both, I get @error = 2 (unknown return type). So I concluded that was the wrong thing to do.

My bad. Apparently I tried it on the input parameter and both, but not on just the return value. Dunno why, but it works now!

Thanks.

Homemade DLLs are fun.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×