When building application for x86, the following code works fine:
#if defined _WIN32
#define LIB_PRE __declspec(dllexport)
#elif defined __unix__
#define LIB_PRE
#else
#define LIB_PRE __declspec(dllexport)
#endif
But gives an error for GCC (ARM). I have found out that __declspec(dllexport) wont work on GCC. If so, what should I use for GCC (ARM)?
Edit:
Its used in many classes. e.g:
class CJsonValueString : public CJsonValue
{
private:
jstring value;
public:
LIB_PRE CJsonValueString(jstring value);
LIB_PRE CJsonValueString(const CJsonValueString * value);
LIB_PRE jstring ToString() const;
LIB_PRE int ToInt() const;
LIB_PRE int64 ToInt64 () const;
LIB_PRE float ToFloat () const;
LIB_PRE void GetValue(jstring & str) const;
};
Basically, you probably don't need anything special. But if you want (and if working on shared objects, i.e. *.so files), learn more about visibility pragmas and visibility function attributes
And the question is more target operating system specific than target machine specific. (I would imagine that an ARM running some obscure Windows8/ARM system would also need your __declspec; conversely, your __declspec has no sense on Linux/x86).
Here's a simplified version of what we use in our code.
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
#if defined(__NT__) // MS Windows
#define idaapi __stdcall
#define ida_export idaapi
#if defined(__IDP__) // modules
#define idaman EXTERNC
#else // kernel
#if defined(__X64__) || defined(__NOEXPORT__)
#define idaman EXTERNC
#else
#define idaman EXTERNC __declspec(dllexport)
#endif
#endif
#define ida_local
#elif defined(__UNIX__) // for unix
#define idaapi
#if defined(__MAC__)
#define idaman EXTERNC __attribute__((visibility("default")))
#define ida_local __attribute__((visibility("hidden")))
#else // Linux
#if __GNUC__ >= 4
#define idaman EXTERNC __attribute__ ((visibility("default")))
#define ida_local __attribute__((visibility("hidden")))
#else
#define idaman EXTERNC
#define ida_local
#endif
#endif
#endif
On Linux/OS X, we compile all code by default with -fvisibility=hidden -fvisibility-inlines-hidden and mark up stuff we want to export with idaman, e.g.
idaman bool ida_export set_enum_width(enum_t id, int width);
Since you're exporting C++ methods, you'll probably want to skip the extern "C" part.
Related
C++20 added std::source_location as a replacement for the debugging macros __LINE__, __FILE__, etc.
This is great. I have a macro that builds up a variable declaration in order to log and profile a block of code using said macros:
#define TOKEN_PASTE_SIMPLE(x, y) x##y
#define TOKEN_PASTE(x, y) TOKEN_PASTE_SIMPLE(x, y)
#define TOKEN_STRINGIZE_SIMPLE(x) #x
#define TOKEN_STRINGIZE(x) TOKEN_STRINGIZE_SIMPLE(x)
//...
#if defined PROFILE_LOG_SCOPE || defined PROFILE_LOG_SCOPE_FUNCTION
#undef PROFILE_LOG_SCOPE
#undef PROFILE_LOG_SCOPE_FUNCTION
#endif
#ifdef PROFILE_BUILD
#define PROFILE_LOG_SCOPE(tag_str) ProfileLogScope TOKEN_PASTE(plscope_, __LINE__)(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION() PROFILE_LOG_SCOPE(__FUNCSIG__)
#else
#define PROFILE_LOG_SCOPE(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION()
#endif
However, replacing the macros with the source_location version breaks because the function calls are not evaluated before the macro expansion.
#define TOKEN_PASTE_SIMPLE(x, y) x##y
#define TOKEN_PASTE(x, y) TOKEN_PASTE_SIMPLE(x, y)
#define TOKEN_STRINGIZE_SIMPLE(x) #x
#define TOKEN_STRINGIZE(x) TOKEN_STRINGIZE_SIMPLE(x)
//...
//TODO: Replace __LINE__ with std::source_location::line
//TODO: Replace __FUNCSIG__ with std::source_location::function_name
#if defined PROFILE_LOG_SCOPE || defined PROFILE_LOG_SCOPE_FUNCTION
#undef PROFILE_LOG_SCOPE
#undef PROFILE_LOG_SCOPE_FUNCTION
#endif
#ifdef PROFILE_BUILD
#define PROFILE_LOG_SCOPE(tag_str) ProfileLogScope TOKEN_PASTE(plscope_, std::source_location::current().line())(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION() PROFILE_LOG_SCOPE(std::source_location::current().function_name())
#else
#define PROFILE_LOG_SCOPE(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION()
#endif
QUESTION
How would I get the above to work?
I ultimately went with a hybrid approach. That is, Use __LINE__ to generate the variable name and pass in std::source_location::current() as a default parameter:
//...
class ProfileLogScope {
public:
explicit ProfileLogScope(const char* scopeName = nullptr, std::source_location location = std::source_location::current()) noexcept;
//...
};
ProfileLogScope::ProfileLogScope(const char* scopeName, std::source_location location) noexcept
: m_scope_name(scopeName)
, m_time_at_creation(TimeUtils::Now())
, m_location(location)
{
/* DO NOTHING */
}
ProfileLogScope::~ProfileLogScope() noexcept {
const auto now = TimeUtils::Now();
TimeUtils::FPMilliseconds elapsedTime = (now - m_time_at_creation);
DebuggerPrintf(std::format("ProfileLogScope {} in file {} on line {} took {:.2f} milliseconds.\n", m_scope_name != nullptr ? m_scope_name : m_location.function_name(), m_location.file_name(), m_location.line(), elapsedTime.count()));
}
//...
#define TOKEN_PASTE_SIMPLE(x, y) x##y
#define TOKEN_PASTE(x, y) TOKEN_PASTE_SIMPLE(x, y)
#define TOKEN_STRINGIZE_SIMPLE(x) #x
#define TOKEN_STRINGIZE(x) TOKEN_STRINGIZE_SIMPLE(x)
//...
#if defined PROFILE_LOG_SCOPE || defined PROFILE_LOG_SCOPE_FUNCTION
#undef PROFILE_LOG_SCOPE
#undef PROFILE_LOG_SCOPE_FUNCTION
#endif
#ifdef PROFILE_BUILD
#define PROFILE_LOG_SCOPE(tag_str) auto TOKEN_PASTE(plscope_, __LINE__) = ProfileLogScope{tag_str}
#define PROFILE_LOG_SCOPE_FUNCTION() auto TOKEN_PASTE(plscope_, __LINE__) = ProfileLogScope{nullptr}
#else
#define PROFILE_LOG_SCOPE(tag_str)
#define PROFILE_LOG_SCOPE_FUNCTION()
#endif
I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC.
The gcc way is quite straight using the __attribute__ keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things.
Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)
Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void finalize(void)
{
printf( "finalize\n");
}
INITIALIZER( initialize)
{
printf( "initialize\n");
atexit( finalize);
}
int main( int argc, char** argv)
{
printf( "main\n");
return 0;
}
You are probably interested in DllMain.
I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)
Untested, but this should at least allow the same code to work in both MSVC and GCC.
#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
void fn(void) __attribute__((constructor))
#endif
static constructor(foo);
void foo() {
...
}
I tried the last answer in MSVC like
#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that
#ifdef _MSC_VER
#define INITIALIZER(f) \
static void f();\
static int __f1(){f();return 0;}\
__pragma(data_seg(".CRT$XIU"))\
static int(*__f2) () = __f1;\
__pragma(data_seg())\
static void f()
#else
#define INITIALIZER(f) \
__attribute__((constructor)) static void f()
#endif
I was wondering if it's possible to use C constructors in VC just as it is possible to use them in GCC.
The gcc way is quite straight using the __attribute__ keyword, unfortunately VC doesn't seem to even know this keyword, as I'm not a Win32 programmer I wonder if there's some sort of equivalent keyword for such things.
Just to note - this is a C program, not a C++ or C# even, (as 'twas quite easy to do that in those languages)
Below C code demonstrates how to define a void(void) function to be called at program/library load time, before main executes.
For MSVC, this places a pointer to the function in the user initializer section (.CRT$XCU), basically the same thing the compiler does for the constructor calls for static C++ objects. For GCC, uses a constructor attribute.
// Initializer/finalizer sample for MSVC and GCC/Clang.
// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
#define INITIALIZER(f) \
static void f(void); \
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
static void f(void)
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void finalize(void)
{
printf( "finalize\n");
}
INITIALIZER( initialize)
{
printf( "initialize\n");
atexit( finalize);
}
int main( int argc, char** argv)
{
printf( "main\n");
return 0;
}
You are probably interested in DllMain.
I don't think there's a way to avoid using C++ features with MSVC. (MSVC's C support sucks anyways.)
Untested, but this should at least allow the same code to work in both MSVC and GCC.
#if defined(_MSC_VER)
struct construct { construct(void (*f)(void)) { f(); } };
#define constructor(fn) \
void fn(void); static constructor constructor_##fn(fn)
#elif defined(__GNUC__)
#define constructor(fn)
void fn(void) __attribute__((constructor))
#endif
static constructor(foo);
void foo() {
...
}
I tried the last answer in MSVC like
#ifdef _MSC_VER
#pragma section(".CRT$XCU",read)
#define INITIALIZER2_(f,p) \
static void f(void); \
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void f(void)
#ifdef _WIN64
#define INITIALIZER(f) INITIALIZER2_(f,"")
#else
#define INITIALIZER(f) INITIALIZER2_(f,"_")
#endif
#else
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
but INITIALIZER(f) can't appear in 2 different files with the same function name passed to INITIALIZER, the following definition will allow that
#ifdef _MSC_VER
#define INITIALIZER(f) \
static void f();\
static int __f1(){f();return 0;}\
__pragma(data_seg(".CRT$XIU"))\
static int(*__f2) () = __f1;\
__pragma(data_seg())\
static void f()
#else
#define INITIALIZER(f) \
__attribute__((constructor)) static void f()
#endif
I have a .lib which has a function that I want to make into a DLL.
In the project properties, I have done 2 things,
1. In the C/C++ -> General -> Additional Directories: added the path for the .h file.
2. In the Linker-> General -> Additional Dependies: added the path for the .lib file
Then I made an .h file
#ifndef _DFUWRAPPER_H_
#define _DFUWRAPPER_H_
#include <windows.h>
#include "DFUEngine.h"
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void helloworld(void);
__declspec(dllexport) void InitDLL();
#ifdef __cplusplus
}
#endif
#endif
and made the .cpp file
#include "stdafx.h"
#include "stdio.h"
#include "DFUWrapper.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
void helloworld(void)
{
printf("hello world DFU");
}
DFUEngine* PyDFUEngine()
{
return new DFUEngine();
}
void delDFUEngine(DFUEngine *DFUe)
{
DFUe->~DFUEngine();
}
void PyInitDLL(DFUEngine *DFUe)
{
return DFUe->InitDLL();
}
I made a test with the function helloword. I can see this function in the DLL but not the InitDLL function.
How can I come around this? Please help
Define the following in your DLL header file
#if defined (_MSC_VER)
#if defined (MY_DLL_EXPORTS)
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif
#else
#define MY_EXPORT
#endif
Declare your function using that macro
#ifdef __cplusplus
extern "C" {
#endif
MY_EXPORT void helloworld(void);
MY_EXPORT void InitDLL();
#ifdef __cplusplus
}
#endif
And in your .cpp
MY_EXPORT void helloworld(void)
{
printf("hello world DFU");
}
MY_EXPORT void InitDLL()
{
/// blahblah
}
Compile your DLL with MY_DLL_EXPORT defintion....
But be sure that it's not define when you want IMPORT ....
I like exporting functions from DLLs using .DEF files.
This has the added benefit of avoiding name mangling: not only the C++ complex mangling, but also the one happening with __stdcall and extern "C" functions (e.g. _myfunc#12).
You may want to simply add a DEF file for your DLL, e.g.:
LIBRARY MYDLL
EXPORTS
InitDLL #1
helloworld #2
... other functions ...
In my project there are 3 possible types of files: pure C/Objective-C, pure C++ or Objective-C++ code.
How to divide functions in .h file with #define directives into parts to make this file available for all these files? I don't want to rename all the .m files to .mm because of problems with refactoring.
I know that I can write .h file in C which uses C++ .cpp file using the following code:
#ifndef Chadstone_CCCWrapper_h
#define Chadstone_CCCWrapper_h
#ifdef __cplusplus
#include <string.h>
extern "C"
{
#endif
void minMaxCoordinates(char *c, float *minX, float *minY, float *maxX, float *maxY);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
but what if I want to add functions with using of NSString or list<...>.
You can find it in standard pch-file genarated by Xcode:
#ifdef __OBJC__
#endif
Also you need use CF_EXPORT macro when declaring function to prevent linkage errors.
Example:
#ifndef SOME_H_FILE
#define SOME_H_FILE
#ifdef __OBJC__
#interface SomeObjClass: NSObject
#end
CF_EXPORT void SomeFunctionWithNSString(NSString* str);
#endif
#ifdef __cplusplus
class SomeCPlusPlustClass
{
};
CF_EXPORT void someFunctionWithList(const list<int>& intList);
#ifdef __OBJ__
CF_EXPORT void someComplicatedFunction(NSString* str, const list<int>& intList);
#endif
#endif
CF_EXPORT void someFunction();
typedef struct _SomeStruct
{
} SomeStruct;
#endif