Why does my Game Maker DLL give an access violation? - c++

I found a tutorial about making your first C++ DLL, which I wanted to try by making a function that calculates the octave number of a certain frequency. I first tried the example function, multiplying two values, and that worked. Then I put my calculating function, which I first tested in a standard c++ project, in the DLL code. Now when I want to call the function in Game Maker, it gives me this popup and when I click the OK button the program hangs.
Does anyone have an idea what could cause this access violation?
Compiler information: I am using NetBeans IDE 7.3 in combination with Cygwin 4 (gcc).
Compiled and tested on Windows 7.
DLL code:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <cstdio>
#include <windows.h>
#define GMEXPORT extern "C" __declspec (dllexport)
double A440 = 440;
GMEXPORT double __cdecl SampleFunction(double a, double b) {
return a * b;
}
GMEXPORT int __cdecl freqGetOctave(double f) {
double a = 12*log2(f/(A440/16))+.505;
int c = (int)(a+9)/12;
return c;
}
Game Maker code:
//script: dll_init
globalvar _exmpl,_freq;
var dll_name;
dll_name = "c:\Users\<me>\Documents\NetBeansProjects\GMDLLtest\dist\Debug\Cygwin_4.x-Windows\libGMDLLtest.dll";
_exmpl = external_define(dll_name, "SampleFunction", dll_cdecl, ty_real, 2, ty_real, ty_real);
_freq = external_define(dll_name, "freqGetOctave", dll_cdecl, ty_real, 1, ty_real);
//script: example
return external_call(_exmpl,argument0,argument1);
//script: freq_octave
return external_call(_freq,argument0);
//Watch Excpressions in Debug Screen:
example(3,3) 9
freq_octave(440) [error popped up:]
// [Access violation at address 00405B33 in module 'DLLtest.exe'.
// Read of access 00000004.]

Regarding these exported functions:
Plug-in functions must have a specific format. They can have between 0 and 16 arguments, each of which can either be a real number (double in C) or a null-terminated string. (For more than 4 arguments, only real arguments are supported at the moment.) They must return either a real or a null-terminated string.
Yours returns an integer, not a double. Game Maker will be trying to interpret that integer as a double, which does not go well.
http://gamemaker.info/en/manual/414_00_dlls

Related

Why can't I use my function in the header file?

main.h: header
#ifndef _MAIN_H
#define _MAIN_H
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct ComplexNum
{
double real;
double img;
}mc;
char *JustShow(mc );
#endif // _MAIN_H
cal.cpp : function defined in another file called
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "main.h"
char *JustShow(mc a)
{
char str1[100];
char str2[100];
char str3 [100];
sprintf(str1,"%f",a.real);
sprintf(str2,"%f",a.img);
strcat(str1," + ");
strcat(str1,str2);
strcat(str1,"i");
return(str1);
}
I tried to use the JustShow function in another file, but the compiler said undefined reference to 'JustShow'
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "main.h"
int main()
{
mc y;
y.img = 4;
y.real = 3;
printf("%s",JustShow(y));
}
I am so confused why can't I use the function JustShow when I had already added "main.h". I am also confused why should we define the functions in the source file instead of the header.
I'm sorry if this is the basic knowledge I should learn about and not ask others.
I'm going to call the third piece of code "main.cpp".
why can't I use the function JustShow when I had already added "main.h".
Header files only inform a compiler that a function, variable or constant exist. You need to compile cal.cpp with main.cpp: g++ main.cpp cal.cpp -o main
I am also confused why should we define the functions in the source file instead of the header.
It makes code more organised.
It speeds up compile time.
You can read more about header files here
Some advice for your code:
Function JustShow is incorrect. Arrays are just pointers and you are returning a pointer to a local variable that are deleted after function returns. It means that it will be overwritten and you will lose data there (and trying to write there may crash your program). In order to make it work you can:
Give an array as an argument to the function. Then we would have void JustShow(mc a, char* str1);
create new array with new (or malloc if you wirte in C, not C++).
You don't need to concat so much. sprintf can do all of that:
void JustShow(mc a, char* str1) {
sprintf(str1,"%f + %fi", a.real, a.img);
}

how to make a function return an array? for making DLL to use in VB.NET

i am trying to make a c++ DLL project in VS2017 to use in a VB.NET VS2017 project.
the c++ code;
MyCudaLib.h
#ifndef DLL3_H
#define DLL3_H
#ifdef DLL3_EXPORTS
#define DLL3_API __declspec(dllexport)
#else
#pragma message("automatic link to MyCudaLib.LIB")
//#pragma comment(lib, "MyCudaLib.lib")
#define DLL3_API __declspec(dllimport)
#endif
int* __stdcall test_array();
#endif //DLL3_H
MyCudaLib.cpp
#include <stdio.h>
#include "MyCudaLib.h"
#include <Windows.h>
#include <stdexcept>
#include <sstream>
using namespace std;
#define DLL3_EXPORTS
BOOL APIENTRY DllMain(HANDLE /*hModule*/,
DWORD ul_reason_for_call,
LPVOID /*lpReserved*/
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int* __stdcall test_array()
{
int arr[]{ 30,50,60,70 };
return arr;
}
in VB part of the code
Private Declare Function test_array Lib "MyCudaLib.dll" () As Integer()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Console.WriteLine(test_array(0))
End Sub
is my exporting part of code is wrong? c++ part compiled wtihout error but VB part of the code wont work gives error.
System.Runtime.InteropServices.MarshalDirectiveException: ''return value' cannot arranged.
Note: My point to make a proper working function in c++ is to write a CUDA code to program the GPU. I can write and compile code in CUDA in c++ without problem. But students in my class cannot program in c++ and i can't write more complex code with c++. So, i thought, if i can use the cuda function outside the c++ environment, we all can code it with vb or other languages.
Sure your function compiles fine - it is defined as a function returning a single int and does so as well (return *arr; is equivalent to return arr[0];).
From MarshalDirectiveException
The exception that is thrown by the marshaler when it encounters a MarshalAsAttribute it does not support.
As you did not provide an English error message, I can only guess what's happening now, but there are only few options available:
You have yet another error with your marshaling not visible here.
The function is not recognised due to C++ name mangling (see below).
Incompatibility between int returned in function and expected array is recognised.
The int is interpreted as pointer – but pointer size does not match and the type cannot be marshaled at all.
If you want to return an array, you need to define your function as such:
int* getArray()
// ^
{
static int a[] = {1, 2, 3};
// ^^^^^^ we cannot return an array with local storage duration, so make it
// static, global, or allocate one on heap (new int[]; but assure the
// array to be delete[]d appropriately again to avoid memory leak)
return a; // NOT dereferenced!
}
Be aware that you have C++ name mangling applied. You might possibly prefer a C-kompatible interface:
extern "C" int* getArray();
However, you cannot return C++ data types this way like std::vector – which in most cases even is preferrable, though, as those types usually are incompatible across different implementations (DLL compiled with MSVS, EXE with GCC/MinGW) anyway.
Finally be aware that via a pointer, you lose information about array size! You need to find other means to provide this information to the user of your library.

can't understand the code that shedskin generates

for example I have a function in python that I want to convert to c++ (or call from c++ but I don't want to depend on python interpretor)
simple python function
//test.py
def my_sum(x,y):
print "Hello World!"
return x*x+y
I run shedskin and have
//test.cpp
#include "builtin.hpp"
#include "test.hpp"
namespace __test__ {
str *__name__;
void __init() {
__name__ = new str("__main__");
}
} // module namespace
int main(int, char **) {
__shedskin__::__init();
__shedskin__::__start(__test__::__init);
}
//test.hpp
#ifndef __TEST_HPP
#define __TEST_HPP
using namespace __shedskin__;
namespace __test__ {
extern str *__name__;
} // module namespace
#endif
ugly code and there is no my function my_sum and code depends on "builtin.hpp". is it possible to convert only function?
or
I want to call function from my c++ code something like
int sum= py.my_sum(3,5);
how can I do this?
or
maybe I can do DLL or Lib from python code that I can use in c++ code?
notice the warning that shedskin gives for this program:
*WARNING* test.py:1: function my_sum not called!
it is also mentioned in the documentation that for compilation to work, a function should be called (directly or indirectly), as it's not possible to do type inference otherwise.. how to determine the types of the arguments of my_sum, if there's not even a single call to it..? :-)
adding this, for example:
if __name__ == '__main__':
my_sum(1,1)
makes my_sum appear in the generated C++ code, which can potentially be called from another C++ program.

Neko Dlls in Haxe C++ target

I am trying to use Neko dlls (written in C++) with the C++ target of Haxe. I am able to call the functions in haxe but not able to pass values.
This is the C++ code -
value Hello(value h)
{
cout << val_int(h);
return val_int(1);
}DEFINE_PRIM(Hello, 1);
This is the Haxe code -
class Main
{
var load = cpp.Lib.loadLazy( "ndll" , "Hello", 1 );
static function main()
{
load(1);
}
}
It executes only if the function does not take parameters. Also, the value that is returned form the C++ function to Haxe is null.
This code actually works perfectly when I compile for the neko target, but it doesn't seem to work with the cpp target.
Any help is appreciated.
Here's the fully corrected C++ code :
#define IMPLEMENT_API
/* Will be compatible with Neko on desktop targets. */
#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX)
#define NEKO_COMPATIBLE
#endif
#include <hx/CFFI.h>
#include <stdio.h>
/* Your hello function. */
value hello(value h)
{
printf("%i\n", val_int(h));
return alloc_int(1);
}
DEFINE_PRIM(hello, 1);
/* Main entry point. */
extern "C" void mylib_main()
{
// Initialization code goes here
}
DEFINE_ENTRY_POINT(mylib_main);
What's important is that every value given as an argument to a primitive or returned by a primitive must be of the type value. That's why your parameter and return didn't work.
val_int is used to convert a value into a native C type, so your printing code was correct. But your return was wrong : you can't return a C int type when the function expects you to return a value to Haxe. You need to create a new Haxe Int type and return it. This is done with the help of alloc_int.
Here's the Haxe part of the code as a reference :
class Main
{
static var hello = cpp.Lib.load("myLib", "hello", 1);
static function main()
{
var myReturnedInt:Int = hello(1);
}
}
A few helpful links :
Neko C FFI
Neko FFI tutorial
CPP FFI notes
In order for this to work, you'll have to add to the header of your cpp file:
#define IMPLEMENT_API
#include <hx/CFFI.h>
(instead of neko's headers)
If you want the ndll to run on both neko and hxcpp, you should also add
#define NEKO_COMPATIBLE
before the hx/CFFI.h include.
You can compile using whatever is best for you, but I recommend using a Build.xml to generate your ndll, since it will automatically add the include and lib paths correctly for hxcpp's headers. You can see an example of a very simple Build.xml here:
http://pastebin.com/X9rFraYp
You can see more documentation about hxcpp's CFFI here: http://haxe.org/doc/cpp/ffi

translate_address in c++\linux

i am trying to make user threads in C++, so while trying to initialize them i am getting a compiler error :translate_address was not declared in this scope
#include <iostream>
#include <cstdlib>
#include <csignal>
#include <csetjmp>
#define JB_SP 6 //Location in the code
#define JB_PC 7 //Stack pointer
#define STACK_SIZE 10
typedef unsigned long address_t; //64bit address
sigjmp_buf jbuf[3];
char stack1[STACK_SIZE];
void f(){
}
void setup(){
unsigned int sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(jbuf[0],1);
(jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&jbuf[0]->__saved_mask);//empty saved signal mask
}
int main(){
return 1;
}
am i meant to include it some how? or is there a different problem?
thank you.
translate_address is not a Linux function. If you're referring to some kind of book or example code, it should explain where you're supposed to get this function from. If it doesn't, chances are it's not meant for Linux (or is a really, really bad reference/example).
Furthermore, you should NOT modify the contents of jmp_buf or sigjmp_buf directly. These are architecture and platform-dependent structures, and only the C library is allowed to mess with them. Since the contents of the structures are OS-dependent, if you're using a reference intended for some other OS when modifying sigjmp_buf, Bad Things will happen.
You should instead either use setcontext, getcontext, and makecontext for user threads (fibers) or pthread_create for OS-level threads.