www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Call C function - Access violation

reply TheDGuy <loder.feuer googlemail.com> writes:
I get an access violation with this code:

extern(C) char* write(char* text);

void main(string[] args){
	char[] text = "Hello World".dup; //.dup converts string to char[]
	text ~= '\0'; //append

	char* result = write(text.ptr); //you need .ptr
	const(char)[] s = cstr2dstr(result);
	writeln(s);
	readln(); //keep the window open
}

auto cstr2dstr(inout(char)* cstr)
{
	return cstr ? cstr[0 .. strlen(cstr)] : "";
}

--

#include std.stdio;

char* write(char* text){
	return text;
}
Jan 03 2016
next sibling parent reply anonymous <anonymous example.com> writes:
On 03.01.2016 13:30, TheDGuy wrote:
 I get an access violation with this code:

 extern(C) char* write(char* text);

 void main(string[] args){
      char[] text = "Hello World".dup; //.dup converts string to char[]
      text ~= '\0'; //append

      char* result = write(text.ptr); //you need .ptr
      const(char)[] s = cstr2dstr(result);
      writeln(s);
      readln(); //keep the window open
 }

 auto cstr2dstr(inout(char)* cstr)
 {
      return cstr ? cstr[0 .. strlen(cstr)] : "";
 }

 --

 #include std.stdio;

 char* write(char* text){
      return text;
 }
Works for me after adding the needed imports and removing the wrong include from the C file. Is this really the actual code you're running? Doesn't your C compiler reject that include? gcc does.
Jan 03 2016
parent reply TheDGuy <loder.feuer googlemail.com> writes:
 Works for me after adding the needed imports and removing the 
 wrong include from the C file. Is this really the actual code 
 you're running? Doesn't your C compiler reject that include? 
 gcc does.
Okay, i think this C code should work (checked with cpp.sh): #import <stdio.h> char* write(char* text){ return text; } int main(void){ return 0; } but i still get the access violation.
Jan 03 2016
parent reply anonymous <anonymous example.com> writes:
On 03.01.2016 14:01, TheDGuy wrote:
 Okay, i think this C code should work (checked with cpp.sh):

 #import <stdio.h>
 char* write(char* text){
      return text;
 }
 int main(void){
      return 0;
 }
Uh, no. 1) In C it's include, not import. 2) Now you have two main functions, that can't work. You shouldn't get a segfault, though. You should get some compile/link error. Are you compiling the right files? Can the segfault be from something other than your program?
Jan 03 2016
parent anonymous <anonymous example.com> writes:
On 03.01.2016 14:12, anonymous wrote:
 You shouldn't get a segfault, though. You should get some compile/link
 error. Are you compiling the right files? Can the segfault be from
 something other than your program?
Oh, I see what's probably happening: You compile the D program, but you don't compile and/or don't link the C object file. It segfaults then when trying to call the C function. You need to compile the C file and pass it to dmd or the linker. For example: gcc -c -otest.c.o test.c dmd test.d test.c.o ./test
Jan 03 2016
prev sibling parent reply Gary Willoughby <dev nomad.so> writes:
On Sunday, 3 January 2016 at 12:30:34 UTC, TheDGuy wrote:
 I get an access violation with this code:

 ...
There are a few things you can do to improve your code to make it easier to debug. 1. When converting a D string to a char pointer for use with C, use `std.string.toStringz`: 2. When converting a char pointer to a D string use `std.conv.to!(string)`: 3. Define C-style char pointers in D as `const(char)*`. 4. Don't use the variable name `text` as it conflicts with `std.conv.text`. I think I've noticed one problem with the code above. You are using `text.ptr`. You shouldn't do that because you are passing a pointer not an array. Just use `text`.
Jan 03 2016
parent reply Gary Willoughby <dev nomad.so> writes:
On Sunday, 3 January 2016 at 13:23:25 UTC, Gary Willoughby wrote:
 I think I've noticed one problem with the code above. You are 
 using `text.ptr`. You shouldn't do that because you are passing 
 a pointer not an array. Just use `text`.
Forget this line, my mistake. Use `toStringz` and pass a pointer instead of an array.
Jan 03 2016
parent reply TheDGuy <loder.feuer googlemail.com> writes:
On Sunday, 3 January 2016 at 13:25:04 UTC, Gary Willoughby wrote:
 On Sunday, 3 January 2016 at 13:23:25 UTC, Gary Willoughby 
 wrote:
 I think I've noticed one problem with the code above. You are 
 using `text.ptr`. You shouldn't do that because you are 
 passing a pointer not an array. Just use `text`.
Forget this line, my mistake. Use `toStringz` and pass a pointer instead of an array.
Hi and thanks for your answer. My code looks now like this: void main(string[] args){ const(char)* val = "Hello World".std.string.toStringz; char* result = write(val); const(char)[] s = cstr2dstr(result); writeln(s); readln(); //keep the window open } But now i get the error: "function expected before(), not package std of type void" (refering to line 2). And if i define the variable 'value' as 'const(char)*' i also have to rewrite my C-function to accept const(char)*...
Jan 03 2016
parent reply Gary Willoughby <dev nomad.so> writes:
On Sunday, 3 January 2016 at 19:24:46 UTC, TheDGuy wrote:
 On Sunday, 3 January 2016 at 13:25:04 UTC, Gary Willoughby 
 wrote:
 On Sunday, 3 January 2016 at 13:23:25 UTC, Gary Willoughby 
 wrote:
 I think I've noticed one problem with the code above. You are 
 using `text.ptr`. You shouldn't do that because you are 
 passing a pointer not an array. Just use `text`.
Forget this line, my mistake. Use `toStringz` and pass a pointer instead of an array.
Hi and thanks for your answer. My code looks now like this: void main(string[] args){ const(char)* val = "Hello World".std.string.toStringz; char* result = write(val); const(char)[] s = cstr2dstr(result); writeln(s); readln(); //keep the window open } But now i get the error: "function expected before(), not package std of type void" (refering to line 2). And if i define the variable 'value' as 'const(char)*' i also have to rewrite my C-function to accept const(char)*...
Use an import. import std.string; import std.conv; void main(string[] args) { auto value = toStringz("Hello World"); auto result = write(value); auto s = to!(string)(result); writeln(s); } Also all string literals in D are zero terminated so you could write the call like this: auto result = write("Hello World");
Jan 03 2016
parent reply TheDGuy <loder.feuer googlemail.com> writes:
 Use an import.

 import std.string;
 import std.conv;

 void main(string[] args) {
     auto value  = toStringz("Hello World");
     auto result = write(value);
     auto s      = to!(string)(result);
     writeln(s);
 }

 Also all string literals in D are zero terminated so you could 
 write the call like this:

 auto result = write("Hello World");
Okay, thank you very much! But now i get the access violation error again. If i type: gcc -c -otest.c.o the 'test.c.o' file is generated but if i type: dmd main.d test.c.o i get: 'Error: unrecognized file extension o'?
Jan 03 2016
parent reply anonymous <anonymous example.com> writes:
On 03.01.2016 21:32, TheDGuy wrote:
 If i type:
 gcc -c -otest.c.o

 the 'test.c.o' file is generated but if i type:

 dmd main.d test.c.o i get: 'Error: unrecognized file extension o'?
You're probably on Windows then? dmd doesn't recognize the .o extension on Windows, use .obj instead.
Jan 03 2016
parent reply TheDGuy <loder.feuer googlemail.com> writes:
On Sunday, 3 January 2016 at 21:20:35 UTC, anonymous wrote:
 On 03.01.2016 21:32, TheDGuy wrote:
 If i type:
 gcc -c -otest.c.o

 the 'test.c.o' file is generated but if i type:

 dmd main.d test.c.o i get: 'Error: unrecognized file extension 
 o'?
You're probably on Windows then? dmd doesn't recognize the .o extension on Windows, use .obj instead.
If i rename "test.o" to "test.obj" i get: 'Error: Module or Dictionary corrupt'
Jan 03 2016
parent anonymous <anonymous example.com> writes:
On 03.01.2016 22:37, TheDGuy wrote:
 If i rename "test.o" to "test.obj" i get:

 'Error: Module or Dictionary corrupt'
My guess is, that means that dmd can't handle the object file format that gcc produces. Disclaimer: I don't know much about object formats, gcc, and Windows. I may be mistaken in what I write here. I think there are three object file formats that are relevant for us: * OMF: the format dmd uses by default on 32 bit Windows, * COFF: the format dmd uses on 64 bit Windows and in 32 bit mode with the -m32mscoff switch, * ELF: the format gcc uses by default (on Linux at least, maybe on Windows too). You should probably try to find out what gcc produces (by reading gcc documentation, I supppose). Then you need to get your D compiler and your C compiler to produce the same format. As mentioned, dmd has some switches that affect the used/expected object format: -m32 (OMF) -m64 (COFF) -m32mscoff (COFF). You can also try to get gcc to produce another format. I don't know how to do that. Or you can use another C compiler that produces a different format than gcc. I'd expect Digital Mars's (i.e. Walter's) dmc to be compatible with dmd and produce OMF files. Looks like there's a free download: http://www.digitalmars.com/download/freecompiler.html dmd's COFF mode is supposed to be compatible with Microsoft's Visual Studio. So that would be another option.
Jan 03 2016