How to write a Postgres language handler using MSVC - postgresql

Here is the code, straight out of the sample. 64 bit install, x64 build.
#include "postgres.h"
#include "executor/spi.h"
#include "commands/trigger.h"
#include "fmgr.h"
#include "access/heapam.h"
#include "utils/syscache.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PGDLLEXPORT Datum plsample_call_handler(PG_FUNCTION_ARGS); // <-- the answer!!
PG_FUNCTION_INFO_V1(plsample_call_handler);
Datum
plsample_call_handler(PG_FUNCTION_ARGS)
{
Datum retval;
retval = 42;
return retval;
}
It compiles and links OK. Here is the SQL:
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
AS 'TryPostgresPl.dll'
LANGUAGE C;
CREATE LANGUAGE plsample
HANDLER plsample_call_handler;
And here is the error message.
ERROR: could not find function "plsample_call_handler" in file "C:/Program Files/PostgreSQL/9.5/lib/TryPostgresPl.dll"
SQL state: 42883
So near and yet so far. Really no idea where to look.
Edited to show the answer as per Nick Barnes. Note that a peek with depends.exe showed 2 exports previously, now 3.

The sample in the Postgres docs is squarely targeted at Linux environments; apparently there's a bit more involved in Windows. There is an excellent article by #CraigRinger which explains how to go about it in Visual Studio.
In this case, it looks like you just need to add the following function prototype:
PGDLLEXPORT Datum plsample_call_handler(PG_FUNCTION_ARGS);

For me (Postgres 13 x64, VS2019, MSVC 14.27), it was enough to just add PGDLLEXPORT in front of PG_FUNCTION_INFO_V1, i.e:
PGDLLEXPORT PG_FUNCTION_INFO_V1(my_func);
Looking closer, this expands to the equivalent of:
PGDLLEXPORT extern Datum my_func(PG_FUNCTION_ARGS);
... plus a bunch more stuff
You'll notice that's very similar to what's being done manually in the accepted answer, so this way seems to avoid some duplication. The only difference is the extern keyword; to be honest I don't know enough about C to know why putting PGDLLEXPORT before extern is still valid (rather than after it as I see in all the examples), but the compiler doesn't complain and the extension works.
YMMV especially if these macros change in the future.

Related

OpenCL program showing errors. What can be a possible solution?

I am getting certain errors as shown in the image below. I think there is a problem with the setting up of environment. I am new to this and couldn't figure out how to correct it. Please help.
enter image description here
You try to #include <CL/cl.hpp>, which is not installed with Your OpenCL implementation, check if the #include <CL/cl2.hpp> is (see https://github.com/KhronosGroup/OpenCL-CLHPP).
If You otherwise don't make usage of the OpenCL C++ Wrapper API (see Appendix D in OpenCL 1.2), then You may want to instead include <CL/cl.h> or better yet (to be portable to Apple MacOS):
#if defined(__APPLE__) && defined(__MACH__)
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

Cuda eclipse and time.h, Symbol 'CLOCK_PROCESS_CPUTIME_ID' could not be resolved although program runs

I admit, this is not really a problem, but more an annoying thing: basically in the Eclipse editor, installed by the Cuda toolkit, I am using this function:
/* Get current value of clock CLOCK_ID and store it in TP. */
extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
as the following:
clock_gettime((clockid_t)CLOCK_PROCESS_CPUTIME_ID, &time1);
The "problem" is that CLOCK_PROCESS_CPUTIME_ID is not resolved, and then the whole project appears as containing some error, but if I compile and run, no problem at all
I have included this
#include <time.h>
#include <iostream>
I included also the rt library. How do I make the error go away?
You need to add your includes to your project's preferences:
Right click on your project, choose General/Paths and Symbols. There, you can add your custom include directories that will be browsed by Nsight for symbols.

How do you call a C function from C++ code in the iPhone?

I added the line extern "C" void perlinTest(void); to a C++ header along with the include of the c header file hoping that was all I needed but the compiler complains:
Undefined symbols for architecture i386:
"perlinTest()", referenced from:
CreateRenderer3(IResourceManager*) in Renderer.o
Your C++ code needs to be aware that the function is a C function. To do so, you need to declare it this way:
extern "C" [prototype];
A realistic example for your situation would be:
extern "C" void perlinTest();
The reason for this is that C++ function names are mangled to something that tells about the types of the parameters. At the lowest level, this is what allows overloading: it never really is legal to have two visible symbols that share the same name, so C++ allows them by embedding markers that indicate the types of the parameters in the function names. For instance, void perlinTest() gets mangled as _Z10perlinTestv on my Lion box with g++ (and probably clang++), though this is ABI-specific and will not necessarily be the same on other platforms.
However, C doesn't support overloading, and functions aren't subject to name mangling, so when your C++ code tries to call one, it needs to know that it must not use a mangled name. This is what extern "C" tells the compiler.
If your header files need to be readable from both C and C++, the common practice is to wrap them in an extern "C" block (extern "C" { /* declarations */ }) itself wrapped in an #ifdef __cplusplus preprocessor directive (so the C code doesn't see the extern "C" code).
#ifdef __cplusplus
extern "C" {
#endif
/* header body */
#ifdef __cplusplus
}
#endif
If it is not a library, you do not need any extern C. Iwould be turning to the .c file extensions and how your compiler is configured to recognize it (looks like not as .c code)
Have you actually implemented void perlinTest(void) anywhere?
Initially, you'll likely be able to merely declare the function without actually having to implement it. If none of your other classes/objects actually call perlinTest(), Xcode will gladly build and run your app, and not issue any errors. Since perlinTest() isn't actually referenced from anywhere, it doesn't care that the function isn't actually implemented.
As soon as you attempt to call perlinTest() from one of your other classes (like from CreateRenderer3(IResourceManager*) in Renderer.o), the linker will want to make sure that symbol can be resolved, and if you haven't actually implemented a barebones definition of it (see below), then you'll likely get an error like the one you got.
A minimal implementation like the following should prevent the linking error:
void perlinTest(void) {
}
One trick you can use to debug this is to introduce an intentional error in your perlinTest() function. Then build your app and see if the compiler reports the error. If the app compiles anyway, then your problem is that the file that has this function is not part of the target you are building.
Also note that the error that you pasted is for a i386 architecture, so it can't be iPhone. You are probably building for the iPhone simulator instead.
Edit: next step would be to check that the link command issued by Xcode includes the .o that has the C function. If it does, then you should dump the contents of the .o file with the nm utility, to see what the function name looks like in the .o.

Can't build objective-c project when including Foundation

Sorry in advance if this has been answered, I've searched repeatedly here and the in the apple docs, but haven't found out what is causing this problem. I have a iOS app that is driven by a 'layout' file that contains references to the content. I wanted to create a command line tool to optimize the content and modify the layout file if need. For example, by tiling an image and replacing it in the layout by the tiles.
I thought to create my first ever OSX tool and used the newest Xcode to create a CoreFoundation project, which gives me a main.c like this:
#include <CoreFoundation/CoreFoundation.h>
int main (int argc, const char * argv[])
{
CFShow(CFSTR("Hello, World!\n"));
return 0;
}
which builds fine. I thought to use some of the NS* classes to start working with the command line args, but as soon as I included the Foundation framework and added this line:
#include <Foundation/Foundation.h>
I started to get tons of build errors. I think I'm missing something basic, here, but I can't see it! Did I choose the wrong template? Is there a better one? Or, what's the problem with using Foundation here?
You need to set the file language to Objective C for it to compile. Either that or rename main.c in main.m

Compile Arm Assembly directly in XCode

What is the best way to go about compiling arm assembly code into xcode. I have those assembly files which are generated. Is there a way i can just include the .s file directly into the c code that i have. Or i will need to run an preprocessor first which would generate the .o file which i can link with my files. If that is the case, how do you do it in XCode.
If you could post the exact compiler error xcode is spitting out then I might be able to come up with a better solution but my guess as of now is that you are forgetting to add the _ prefix do you functions in assembly.
.globl _add_in_asm
_add_in_asm:
add r0,r0,#1
bx lr
Now in the C source file
#include <stdio.h>
extern int add_in_asm(int i);
int main(int argc, char* argv[]) {
printf("result:%i\n", add_in_asm(10));
return 0;
}
The program should print
result:11
It appears that you just need to add the .s file into your project. Converting it into inline assembly for C is possible, but also fairly difficult, so I recommend against it.
If you are having linking problems, remember Mach-O will be looking for the assembly methods to be prefixed with underscore. #A Person's example shows this, but does not point it out.
C-declaration
extern int add_in_asm(int i);
links against ASM method:
_add_in_asm
That is the first google result and whilst the answer is good, the actual way for me to do it is (Xcode 7.3.1; using real device)
under Xcode add an empty assembly file and use the code as above but add align statement
.globl _add_in_asm
.align 4
_add_in_asm:
add r0,r0,#1
bx lr
in the AppDelegate.m
add
include <stdio.h> and
under the - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
extern int add_in_asm(int i);
printf("result:%i\n", add_in_asm(10));
Having said that and after it was successfully run, it does not work after I close Xcode and restart it ... well one has to use real device and when restart, it would try to use emulator!!!!
`
/Users/xxx/Documents/myMac-git/testasm/my-testasm.s:18:11: error: invalid operand for instruction
add r0,r0,#1
^
/Users/xxx/Documents/myMac-git/testasm/my-testasm.s:19:7: error: unrecognized instruction mnemonic
bx lr
^
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang failed with exit code 1
`
If you see above message use real devices!