Disclaimer: I'm only getting started in C, so it's likely that I'm missing something obvious, or not thinking the right way! :)
How exactly would I go about using GDI+ in pure C?
As I understand it, GDI+ has wrapped objects made for C++, but underneath it lies a flat API which is accessible through gdiplusflat.h, a C-friendly header.
My problem is that when I #include it, I get the following errors:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(30) : error C2143: syntax error : missing '{' before '__stdcall'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2146: syntax error : missing ')' before identifier 'brushMode'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2061: syntax error : identifier 'brushMode'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ';'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ','
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ')'
and 100 more...
Now, I think these errors are due to GpStatus not being defined because peeking into GdiPlusFlat.h shows that all the functions are of the style:
// WINGDIAPI is #defined as __stdcall
GpStatus WINGDIPAPI
GdipCreatePath(GpFillMode brushMode, GpPath **path);
GpStatus WINGDIPAPI
GdipCreatePath2(GDIPCONST GpPointF*, GDIPCONST BYTE*, INT, GpFillMode,
GpPath **path);
GpStatus WINGDIPAPI
GdipCreatePath2I(GDIPCONST GpPoint*, GDIPCONST BYTE*, INT, GpFillMode,
GpPath **path);
etc...
The problem is that GpStatus is a typedef to Status in GdiPlusGpStubs.h (a C++ header), and Status is itself an enum defined in GdiPlusTypes.h (also a C++ header). I tried defining the enum myself, but for some reason the compiler wouldn't take it!
So... how does one exactly use GDI+ functions in C? Should I just load gdiplus.dll dynamically?
The problem is that gdiplusflat.h really needs many more gdi*.h header files included before it. But many of these header files that have the needed typedef declarations referenced by gdiplusflat.h also contain "class" declarations and other C++ keywords. The C compiler will error out when it sees these lines.
You have two choices.
Simple. Accept the fact that C++ is essentially a superset of C. Then just rename your ".c" file you are trying to compile to have a ".cpp" extension. Your C code will get compiled as C++, but that likely won't change a line of code you write. Then #include gdiplus.h before you #include gdiplusflat.h
Harder. depends on typedef definitions in other header files. The problem is that many of these header files have "class" definitions and C++ keywords that the C compiler will error out on. You'll have to manually port over many of the C declarations into your own header file that gets included before gdiplusflat.h. Here's my feeble attempt. It's not quite done. It gets half of the compilation errors out. But I got too tired and just went with option #1. You could finish it, but option 1 above is so much easier.
x
enum Status
{
Ok = 0,
GenericError = 1,
InvalidParameter = 2,
OutOfMemory = 3,
ObjectBusy = 4,
InsufficientBuffer = 5,
NotImplemented = 6,
Win32Error = 7,
WrongState = 8,
Aborted = 9,
FileNotFound = 10,
ValueOverflow = 11,
AccessDenied = 12,
UnknownImageFormat = 13,
FontFamilyNotFound = 14,
FontStyleNotFound = 15,
NotTrueTypeFont = 16,
UnsupportedGdiplusVersion = 17,
GdiplusNotInitialized = 18,
PropertyNotFound = 19,
PropertyNotSupported = 20,
#if (GDIPVER >= 0x0110)
ProfileNotFound = 21,
#endif //(GDIPVER >= 0x0110)
};
typedef Status GpStatus;
enum FillMode
{
FillModeAlternate, // 0
FillModeWinding // 1
};
typedef FillMode GpFillMode;
struct GpPath {};
typedef float REAL;
struct GpPointF
{
REAL x;
REAL y;
};
struct GpPoint
{
int x;
int y;
};
#include <gdiplusflat.h>
You can use Flat API from MSDN. There's a straight conversion from Flat API (C) to GDI+ (C++), I think it's fairly simple.
P.S: However you can still use GDI straight in C.
Related
I'm writing a simple code in C language, and this works.
Which compiles and excutes with no errors, gives the expected output.
#include <stdio.h>
int main(void) {
struct SiteTemplate {
int views;
};
int visit(struct SiteTemplate *site) {
site -> views++;
return 0;
}
struct SiteTemplate site;
site.views = 0;
visit(&site);
printf("%d\n", site.views);
return 0;
}
But in my VS Code, with C_Cpp linting is on, my IDE shows the following error and other problems with it.
declaration is incompatible with previous "visit" (declared at line 8)
Having a screenshot of it:
This error linting is really confusing me since my code works with gcc, it doesn't show any error when compiling.
And also, if I move my struct and function definition to the global level instead of inside main(), then the errors don't exist anymore... But what's the error declaration is incompatible? Or is there any problem with my code?
Click here to view the another screenshot to save whitespaces of this page.
By the way, the version of my VS Code is 1.52.0, with default C_Cpp linting.
Nested function definition is not standard C, it's supported by compiler extensions. According to C standard, any function definition needs to appear outside of any other function definition.
I am trying to compile one driver in VS, but it shows -
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol __imp__PsGetProcessWow64Process#4 referenced in function _GetProcessModule#8 Garhal C:\Users\Raitis\source\repos\GarHal_CSGO\Garhal\memory.obj 1
Quickly enough, I found a place, where this PsGetProcessWow64Process is being used https://prnt.sc/uffavf
But it is defined, and it's even an official ntos.h function. Just pressing F12 on it finds it easily - https://prnt.sc/uffbjg
Screenshot from error list - https://prnt.sc/uffc6t
The problem is that this in undocumented functions and the linker is having a hard time finding where is the function to put a pointer to it in the generated binary, so first include ntifs.h before ntddk.h like this
#include <ntifs.h>
#include <ntddk.h>
it must be before ntddk or you will get weird errors
then add this line :
NTKERNELAPI PVOID PsGetProcessWow64Process(__in PEPROCESS Process);
which is the signature of the function and now you are ready to call that function
another way to get it is using function pointers and resolving it at run time
#include <ntddk.h>
typedef struct _PEB32 {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR Spare;
ULONG Mutant;
ULONG ImageBaseAddress;
ULONG/*PPEB_LDR_DATA32*/ Ldr;
} PEB32, *PPEB32;
typedef PPEB32 (NTAPI * pfn_PsGetProcessWow64Process) (PEPROCESS Process);
pfn_PsGetProcessWow64Process PsGetProcessWow64Process = NULL;
RtlInitUnicodeString (&usFunctionName, L"PsGetProcessWow64Process");
PsGetProcessWow64Process = (pfn_PsGetProcessWow64Process) (SIZE_T)MmGetSystemRoutineAddress (&usFunctionName);
pPEB32 = PsGetProcessWow64Process (pEProcess);
I am using Microsoft Visual Studio 2010 to write a C code. This is the piece of code that I defined :
#define setImagVal_Matrix(matrix,type,x,y,val) \
(getImagVal_Matrix(matrix,type,x,y) = (val))
Then I am using it inside this function :
for(bands=0; bands < no_of_bands; bands++) {
outputmatrix[bands] = new_Matrix(yrange,xrange,getDataType_Image(inputImage),getDataFormat_Image(inputImage));
for(r=0; r < no_of_rows; r++) {
for(c=0; c < no_of_cols; c++) {
if(c<x1 || c>x2 || r<y1 || r>y2)
{
continue;
}
else
{
setImagVal_Matrix(outputmatrix[bands],getDataType_Matrix(outputmatrix[bands]),c-x1,r-y1,123);
}
}
}
}
However, it shows me this error on setImagVal_Matrix function call:
"Error:expected an expression"
And when I build the solution , here is the output which shows a syntax error on the same line:
1>c:\cviplab-net-2010\cviplab\crop.c(50): error C2059: syntax error : ')'
After spending couple of hours, I still cannot find the cause of the error . Any idea how to fix it?
EDIT:
I analyzed the pre-processed file and found the syntax error but still I don't know how to fix it. Here is the line which makes the error :
((((((outputmatrix[bands])->data_type) **)((outputmatrix[bands])->iptr))[r-y1][c-x1]) = (123));
the error is for the ) after **
Just stop using macros as functions. Try this:
inline void setImagVal_Matrix(int matrix, int type, int x, int y, int val) {
getImagVal_Matrix(matrix, type, x, y) = val;
}
Change the int types as appropriate, and you'll get the compiler helping you with useful error messages instead of cryptic ones. Heck, it'll even help you figure out the argument types.
Within your macro, you do an assignment to something that does not look like an lvalue. Do you mean ==?
I would like to propose at least to use brackets for the macro arguments:
#define setImagVal_Matrix((matrix),(type),(x),(y),(val)) \
(getImagVal_Matrix((matrix),(type),(x),(y)) = (val))
Also, to see if it is really bracket issue, you can try to look at preprocessed file.
But, actually using macro for this purpose is not a good one practice. If you care about function call you can make the function inline:
inline void setImagVal_Matrix(matrix,type,x,y,val) {
getImagVal_Matrix(matrix,type,x,y) = val;
}
In spite of the fact that inline is only recommendation for the compiler, this will allow to avoid a lot of compilation errors and hardly debugging run-time errors.
Since yesterday, I've been facing a compiling error for my C project. The project itself consists on creating a service that will make some tasks.
I don't what has changed since yesterday, but this morning, my code can't compile anymore.
Here are the errors I have :
c:\path\main.c(56): error C2275: 'SERVICE_TABLE_ENTRY' : illegal use of this type as an expression
c:\program files\microsoft sdks\windows\v7.0a\include\winsvc.h(773) : see declaration of 'SERVICE_TABLE_ENTRY'
c:\path\main.c(56): error C2146: syntax error : missing ';' before identifier 'DispatchTable'
c:\path\main.c(56): error C2065: 'DispatchTable' : undeclared identifier
c:\path\main.c(56): error C2059: syntax error : ']'
c:\path\main.c(57): error C2065: 'DispatchTable' : undeclared identifier
c:\path\main.c(57): warning C4047: 'function' : 'const SERVICE_TABLE_ENTRYA *' differs in levels of indirection from 'int'
c:\path\main.c(57): warning C4024: 'StartServiceCtrlDispatcherA' : different types for formal and actual parameter 1
Here's the code concerned by these errors (from lines 45 to 58) :
int main(int ac, char *av[])
{
if (ac > 1)
{
if (!parse_args(ac, av))
{
aff_error(ARGUMENTS);
return EXIT_FAILURE;
}
}
SERVICE_TABLE_ENTRY DispatchTable[] = {{MY_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
return EXIT_SUCCESS;
}
And here's the code of my ServiceMain function :
void WINAPI ServiceMain(DWORD ac, LPTSTR *av)
{
gl_ServiceStatus.dwServiceType = SERVICE_WIN32;
gl_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
gl_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
gl_ServiceStatus.dwWin32ExitCode = 0;
gl_ServiceStatus.dwServiceSpecificExitCode = 0;
gl_ServiceStatus.dwCheckPoint = 0;
gl_ServiceStatus.dwWaitHint = 0;
gl_ServiceStatusHandle = RegisterServiceCtrlHandler(MY_SERVICE_NAME, ServiceCtrlHandler);
if (gl_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
return;
gl_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
gl_ServiceStatus.dwCheckPoint = 0;
gl_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(gl_ServiceStatusHandle, &gl_ServiceStatus);
}
I couldn't manage to find some answers that fit my problem, could anyone helps ? Thanks !
When you name your source files *.c, MSVC assumes it's compiling C, which means C89. All block-local variables need to be declared at the beginning of the block.
Workarounds include:
declaring/initializing all local variables at the beginning of a code block (directly after an opening brace {)
rename the source files to *.cpp or equivalent and compile as C++.
upgrading to VS 2013, which relaxes this restriction.
You might be using a version of C that doesn't allow variables to be declared in the middle of a block. C used to require that variables be declared at the top of a block, after the opening { and before executable statements.
Put braces around the code where the variable is used.
In your case that means:
if (ac > 1)
{
if (!parse_args(ac, av))
{
aff_error(ARGUMENTS);
return EXIT_FAILURE;
}
}
{
SERVICE_TABLE_ENTRY DispatchTable[] = {{MY_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
This error occurred when transferring a project from one installation to another (VS2015 => VS2010).
The C code was actually compiled as C++ on the original machine, on the target machine the "Default" setting in Project Properties\C/C++\Advanced\Compile as was somehow pointing to C even though the source file was of type *.cpp.
In my small program, errors popped up regarding the placement in code of certain types e.g. HWND and HRESULT as well as on the different format of for loops , and C++ constructs like LPCTSTR, size_t, StringCbPrintf and BOOL. Comparison.
Changing the "Compile as" from Default to Compile as C++ Code (/TP) resolved it.
This will also give you "illegal use of this type as an expression".
WRONG:
MyClass::MyClass()
{
*MyClass _self = this;
}
CORRECT:
MyClass::MyClass()
{
MyClass* _self = this;
}
You might be wonder the point of that code. By explicitly casting to the type I thought it was, when the compiler threw an error, I realized I was ignoring some hungarian notation in front of the class name when trying to send "this"
to the constructor for another object. When bug hunting, best to test all of your assumptions.
My current job at the university is to port a C program from MinGW (windows) to Visual Studio (nmake).
I have got a valid "makefile.vc" file for a very similar C program.
My approach was to adopt the Makefile (i.e. "makefile.vc") to the program I need to port.
All but four C files seem to compile fine. Those four files have various errors for example, syntax errors and "unknown size".
Should I continue with my approach to change the Makefile or use CMAKE instead of nmake?
Is there a tutorial or any other pointer on porting a C program from MinGW/gcc to nmake?
typedef struct {
A_TypeConverter *converter;
char *domain;
} enumeratorConverterEntry;
static enumeratorConverterEntry enumeratorConverterEntries[]; /* line 186 */
error:
f.c(186) : error C2133: 'enumeratorConverterEntries' : unknown size
typedef struct AsmInstructionInfo {
int flags;
CONST char **argTypes; /* line 7 */
int minArgs;
int maxArgs;
int cArgs;
} AsmInstructionInfo;
error:
fAssemble.c(7) : error C2061: syntax error : identifier 'CONST'
..
/* file fStack.c: */
#ifdef CHECK_ACTIVATION_COUNTS
/* code */
#endif
/* more code */
void fShowStack(l_Interp *interp) { /* line 94 */
l_CallFrame *framePtr;
/* more code */
error:
fStack.c(94) : error C2143: syntax error : missing ')' before '*'
fStack.c(94) : error C2143: syntax error : missing '{' before '*'
fStack.c(94) : error C2059: syntax error : ')'
fStack.c(94) : error C2054: expected '(' to follow 'interp'
static enumeratorConverterEntry enumeratorConverterEntries[]; /* line 186 */
That looks like a valid incomplete, forward declaration of an array, which would be valid syntax, except I think for the static qualifier. I don't have a copy of the 'C' standard in front of me, but reading between the lines on the results of Googling "forward declaration of static array" seems to indicate that an incomplete definition of a static array results in undefined behavior, so Microsoft and GNU are legitimately entitled to do whatever they want with it. GNU accepts it, and Microsoft rejects it. As Mark Wilkins points out you should be make the Microsoft compiler happy by replacing it with:
extern enumeratorConverterEntry enumeratorConverterEntries[]; /* line 186 */
In general it's worth noting that the Microsoft compiler only supports the C89 standard, while the GNU compiler supports portions of the C99 standard, and several of their own extensions, depending on the arguments to the compiler.
The errors in fAssemble.c and fStack.c look like one or more preprocessor files are missing or incomplete. You should search your source to find out where CONST and l_Interp are defined, and then figure out why they are not being picked up in the files where the errors are occurring.
I just now tried out that array declaration with MinGW, and it does compile. To make it link, though, it needs the array to be defined elsewhere. The result is that it appears to be the same as the extern storage class:
extern enumeratorConverterEntry enumeratorConverterEntries[];
I'm not sure if there are other subtleties associated with the original declaration using a static storage class for the global.