Fatal error when using FILE* in Windows from DLL - c

Recently, I found a problem with Visual C++ 2008 compiler, but using minor hack avoid it. Currently, I cannot use the same hack, but problem exists as in 2008 as in 2010 (Express).
So, I've prepared for you 2 simple C file: one for DLL, one for program:
DLL (file-dll.c):
#include <stdio.h>
__declspec(dllexport) void
print_to_stream (FILE *stream)
{
fprintf (stream, "OK!\n");
}
And for program, which links this DLL via file-dll.lib:
Program:
#include <stdio.h>
__declspec(dllimport) void print_to_stream (FILE *stream);
int
main (void)
{
print_to_stream (stdout);
return 0;
}
To compile and link DLL:
cl /LD file-dll.c
To compile and link program:
cl file-test.c file-dll.lib
When invoking file-test.exe, I got the fatal error (similar to segmentation fault in UNIX).
As I said early, I had that the same problem before: about transferring FILE* pointer to DLL. I thought, that it may be because of compiler mismatch, but now I'm using one compiler for everything and it's not the problem. ;-(
What can I do now?
UPD:
I've found solution:
cl /LD /MD file-dll.c
cl /MD file-test.c file-dll.lib
The key is to link to dynamic library, but (I did not know it) by default it links staticaly and (hencefore) error occurs (I see why).
P.S. Thanks for patience.

Potential Errors Passing CRT Objects Across DLL Boundaries
There is a specific example for your situation in here. Depending on how you compile your DLL and program, you might have separate copies of the CRT which will result in an access violation.

Related

GCC can't find headers on Windows

I'm new in winAPI and I was learning how code programs with some special functions and such, so I downloaded the Windows's SDK.
Problem is, GCC decided to put the blind glasses and say:
Documents_path.c:6:25: fatal error: KnownFolders.h: No such file or directory
#include<KnownFolders.h>
^
compilation terminated.
I said "OK, next one then" and there's another header with the same problem:
thread.c:3:30: fatal error: processthreadsapi.h: No such file or directory
#include<processthreadsapi.h>
^
compilation terminated.
I checked if these headers are even in my PC and here they are setting with windows.h, which it was working when I tried basic functions with it.
I searched an answer for this problem but didn't find any, either it was a external\binary libraries problem, is it local or not or a macro fix (which it didn't work).
How can I fix the problem?
EDIT:
I'm using VS Code
EDIT2:
This is the code of "Documents_path.c" example:
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<ShlObj.h>
#include<initguid.h>
#include<KnownFolders.h>
#pragma comment(lib, "user32.lib")
int main(){
int a;
PWSTR path = NULL;
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_Documents, 0, NULL, &path);
if(SUCCEEDED(hr)){
printf("path for Documents is: %ls", path);
}
scanf("%d",&a);
CoTaskMemFree(path);
return 0;
}
And I'm reading the basics of winAPI from this website:
https://zetcode.com/gui/winapi/
as for structure of project folder:
C:\Users\ %USER%\Documents\C\dawd
MSVC uses Windows SDK while GCC does not.
On Windows GCC uses MinGW or MinGW-w64 as standard library, which is an open source implementation of Windows API.
So GCC+MinGW will use its own headers and will not look for any Windows SDK. So GCC+MinGW on Windows works without having any Microsoft developer tools installed at all.
MinGW-w64 - which is more recent than MinGW and which supports both Windows 32-bit and 64-bit - exists in a standalone package that can be downloaded from https://winlibs.com/. But you can still use it from an IDE like VSCode or Code::Blocks.
MinGW-w64 has the files like knownfolders.h and processthreadsapi.h which you had issues with.
But be aware that #pragma comment(lib, "user32.lib") is MSVC-specific and will not work in other compilers like GCC. Instead you must use linker flag -luser32. Because you call CoTaskMemFree() you will also need to add -lole32.
I tried your code on my system and it compiles and links fine with:
gcc -c -o Documents_path.o Documents_path.c
gcc -o Documents_path.exe Documents_path.o -luser32 -lole32

How to call functions from a pre-compiled C library within Rust

Long story short, I want to call C code from Rust... I've seen crates like cc and cmake which (to my understanding, which might be wrong) can compile C code for use with the Rust language. Though I am capable of producing a compiled .lib file using the CLion IDE. Now I would like to simply link to said .lib file from Rust and just call the code within, is this possible? I have tried a few things, but they just do not seem to link at all...
project structure:
my_rust_project/
my_c_project/
cmake_build_debug/
...
my_c_project.lib
...
...
a_c_file.h
a_c_file.c
...
src/
main.rs
cargo.roml
build.rs
...
build.rs:
fn main() {
println!("cargo:rustc-link-search=my_c_project/cmake-build-debug/");
println!("cargo:rustc-link-lib=static=my_c_project/cmake-build-debug/my_c_project");
}
main.rs:
#[link(name = "my_c_project/cmake-build-debug/my_c_project", kind = "static")]
extern "C" {
fn hello();
}
fn main() {
unsafe {
//hello(); /* if commented the project compiles... */
}
}
Note how you could comment out any of the two prinln!'s in build.rs as well as the #link directive from main.rs in any combination you could think of (i.e. commenting out #link and leaving the println's, or commenting out one println and leaving the #link, and so on...) and the project will continue to compile, though as soon as you uncomment hello(); from fn main() in main.rs, the project will not compile and produce the following error:
LNK2019: unresolved external symbol hello referenced in function blah blah blah ...
I think there is two possible causes, either the library is not link at all, which seems to be the most logical issue to me, which raises the question: what exactly do the println!'s and #link do in this specific scenarion, they do not cause a panic! or error so they must definitly be doing something right? Whatever it is, it cannot be linking the project.
The other issue I can imagine is that there is in fact proper linking going on-ish? But Rust just doesn't understand where exactly to find the function hello within my_c_project.lib...
For clarity I will provide the contents of my_c_project:
a_c_file.h:
#ifndef MY_C_PROJECT_A_C_FILE_H
#define MY_C_PROJECT_A_C_FILE_H
void hello();
#endif //MY_C_PROJECT_A_C_FILE_H
a_c_file.c:
#include "a_c_file.h"
#include <stdio.h>
void hello() {
printf("Hello, World!\n");
}
I really want to stress that I want to stay away from cc and cmake (crates) since I have the .lib file ready to go... The question remains, how to call the C functions from a .lib file from within a Rust program?
Thanks for the help!
newly tried thing...
changed build.rs to:
fn main() {
println!("cargo:rustc-link-search=my_c_project/cmake-build-debug/");
println!("cargo:rustc-link-lib=static=my_c_project");
}
changed main.rs to:
extern {
fn hello();
}
fn main {
}
renamed my_c_project.lib to libmy_c_project.lib...
This still produces an error:
LINK : fatal error LNK1181: cannot open input file 'libmy_library.lib'
I guess it does not require a .a file per se as it says .lib in the message above.
If anyone ever has this problem... I solved this by continuing the project on Linux using cross compilers to generate the executable for windows.
The matter is to compile everything (source code and libraries/dependencies) for the target platform using the correct compilers ofcourse.

Link with custom function instead of crt one

I'm working on an application which defines it's own printf() to get around differences between the different CRTs out there or because some other platforms don't have it.
When building the application with gcc this automatically seems to work and the custom printf is used instead of libc's one; if I understand it correctly this is because of the order in which object files/libraries appear in the link command or maybe because object files are always searched before CRT libs, correct?
I'd like to do the same using msvc. Just building the project gives the expected 'LNK2005: _printf already defined in printf.obj' because printf is also in msvcrtd.lib. Fair enough. I know about /NODEFAULTLIB but that excludes everything resulting in unresolved references for everything but printf. I scanned through the other linker settings but couldn't find anything which allows this (apart from /FORCE maybe, but the 'might produce an invalid executable' comment doesn't make it sound like a good idea). Also nothing in the module definition file docs; the latter got me thinking it might be possible to create a stub library which has all exports from msvcrt.lib except printf but that seems a brittle solution even if it works.
In the end the question is simple: how do I tell msvc's linker it should skip msvcrt's printf definition and use the one from my printf.obj instead. Basically /NODEFAULTFUNCTION:printf or so. Just an answer for one single executable is ok, though I'd also be interested to know if and how it can be done when building a dll instead where the custom printf is exported: how to tell the linker it should use the export from my .lib instead of msvcrt.lib?
edit simplest repo I could find: create a file main.c:
#include <stdio.h>
int main(int argc, char** argv)
{
printf("Hello");
return 0;
}
and a file printf.c:
int printf(const char *fmt, ...)
{
write(1, "ok\n", 3);
return 3;
}
For VS2013 (though the other versions might work as well): create a new empty C++ project and add both files then build. (For gcc: just gcc main.c printf.c and the resulting a.out prints 'ok')
The culptrit for VS is #include : without that it works ok but I have yet to find out if the original code allows getting rid of it in some way. But even if it does I'd still want to know if this can be solved at the link level.

Call method from source file in another directory

I have a newbie question about the C programming language. I have looked around to find the answer in similar questions but I failed to figure it out.
Assume a simple project consisting of two dirs: src and test. The source and header files are defined by src/main.c, test/foo.h and test/foo.c.
src/main.c:
#include "../test/foo.h"
int main (void) {
int a = VAR; /* works, recognizes declared macro */
some_function(a); /* doesn't work, "undefined reference" */
}
test/foo.h:
#ifndef FOO_H
#define FOO_H
void some_function(int a);
#define VAR 2;
#endif
test/foo.c (redundant but to be complete):
#include "foo.h"
#include <stdlib.h>
void some_function(int a) {
printf("%d", ++a);
}
I created the project in Eclipse and I also compile with it, I figured it wasn't a linking error since the macro gets recognized but the method is not callable.
The reason why I'm using different directories is because I have a lot of files and would like my test code to be separate from my main source code. Note that src and test have the same parent directory.
Any ideas what's going on here? Am I missing something very obvious?
Any help would be much appreciated, thanks in advance!
edit: I'm working on a (Debian) Linux machine and Eclipse uses the gcc compiler.
edit2: Thanks to H2CO3's answer I learned it is indeed a linking error. Since compiling and linking manually every time is quite an overhead, I was wondering if anyone knows how to teach Eclipse to link executables from different directories?
--------------------- SOLUTION ---------------------
edit3: Lol the solution was very easy after all, all I had to do was create a "new source folder" rather than a "new folder". I feel stupid but thanks to you all for replying, H2CO3 in particular!
I figured it wasn't a linking error since the macro gets recognized but the method is not callable.
Non sequitur. Macros are expanded in the preprocessing phase. (And as such, they have nothing to do with linkage at all.) You do have a linker error.
What you have to do is compile both files then link them together, so something like this should work:
gcc -Wall -o dir_one/foo.o dir_one/foo.c
gcc -Wall -o dir_two/bar.o dir_two/bar.c
gcc -o my_program dir_one/foo.o dir_two/bar.o
Also, read this SO question/answer and/or this article to understand how the steps of the compilation process work together. (These are almost the same for C and C++, it's only the name mangling that usually differs.)

How do I set up my code/VS10 to recognize CUDA function calls within .c files?

Basically, I have the compiler compiling my .cu files and I have (I think) full operation within those .cu files, but when I try to call them (kernel<<<1,1>>>(void)), the compiler registers syntax errors due to the CUDA syntax. Also, calls like cudaMalloc fail within c files.
Here are three really short files, so I can tell you where it is erroring.
//kernel.cu
#include "kernel.h"
#include <cuda.h>
#include <cuda_runtime_api.h>
__global__ int kernel(void){
return 5;
}
and
//kernel.h
#ifndef _KERNEL_h_
#define _KERNEL_h_
extern "C" int kernel(void);
#endif
and
//main.c
#include "kernel.h"
#include <cuda.h>
#include <cuda_runtime_api.h>
int main() {
int* device_a;
cudaMalloc( (void**)&device_a, sizeof(int) );
kernel<<<1,1>>>();
}
I got the header file from some of the SDK examples. Also, I have my build configuration set with CUDA 4.2, hence why the .cu file compiles. If I made any incidental syntax errors, it is because I simplified it for posting, not that it is actually in the source, although please mention it just in case.
kernel.cu compiles fine.
kernel.h has an error: "error C2059: syntax error : 'string'" on the "extern..." line. (Could this be because I took that from a c++ example?)
main.c has an error: "error C2065: 'kernel' : undeclared identifier"
and: "error C2059: syntax error : '<'"
but when I comment out the kernel call, so it is just cudaMalloc, I get: "error LNK2019: unresolved external symbol _cudaMalloc#8 referenced in function _main"
and: "fatal error LNK1120: 1 unresolved externals"
Is it something with Visual Studio 2010, or is it something I am not including? From the SDK examples, I can't tell what I'm doing wrong, other then they found a way, I think, to not use the triple bracket (CTRL+F doesn't find any). Any help is appreciated. Thank you in advance!
EDIT: after looking at some more examples, they do use the triple bracket syntax just fine.
EDIT: For those using this as reference, __global__ functions can only return void. If you try to return anything else, as I did, you will receive compiler errors.
Put the functions that invoke CUDA kernel in .cu files.
Set up VS2010 to compile CU files with the CUDA compiler, not the built in one (use the CUDA rules files (Cuda.props, Cuda.xml, Cuda.targets) located within the CUDA SDK).
I recommend placing kernels in files with a different extension (e.g. .curnel files), so that they will not be compiled directly (only if called).
I recommend putting the declaration of the functions that invoke CUDA kernels in .cuh files.

Resources