Type visibilty for a header Share a header file shared between native and managed clients - c++-cli

I have a header file that is included by both a native cpp file and a managed cpp file(compiled with /clr). It includes only native types, but I want to specify that the native types are visible outside the assembly
(see http://msdn.microsoft.com/en-us/library/4dffacbw(VS.80).aspx).
Essentially, I want:
public class NativeClass // The public makes this visible outside the assembly.
{
};
If I include this code from a native cpp, I get the following error:
error C3381: 'NativeClass' : assembly access specifiers are only available in code compiled with a /clr option
Attempted solution:
I'm currently using a preprocessor solution that causes the public to appear when compiling with the managed client, but it does not appear for the native client:
#ifdef __cplusplus_cli
#define CLR_ASSEMBLY_ACCESS_SPECIFIER__Public public
#else
#define CLR_ASSEMBLY_ACCESS_SPECIFIER__Public
#endif
CLR_ASSEMBLY_ACCESS_SPECIFIER__Public
class NativeClass
{
};
Question:
Is this the appropriate way to achieve this, or is there a better way?

Have you tried the make_public pragma listed on the MSDN page you linked to?
Otherwise, the solution you have is perfectly valid. I'm curious to know why you want to export native types from a CLR assembly though.

Related

Using Swift in Objective-C project

Although I have followed and tried everything from This Thread and read all of Apple's Guide of Swift-ObjC interoperability, I'm unable to recognize or use Swift fies in my project.
I have created a Swift file that declares/defines a class called TorusView that inherits from UIView. I've tried to gain access to this class in another class MenuView by importing the bridging header, importing the Swift class, importing the class with the syntax *-swift.h (which seems to now be *.swift.hin Xcode7.2). I've made all of the modifications to my target build settings recommended in that lengthy Stack question and a variety of others from google searches.
Nothing I've tried has allowed me to create a TorusView objective in my objective-C class.
You need to import a header file YourAppName-Swift.h, it contains all the public (and internal if same target) declared types in Swift.
first: Build Settings --> defines module --> YES.
second:Product Module Name -->YOUR project NAME.
last:improt "YOUR project NAME-Swift.h" in your Object-c file
like this:
enter image description here

Exporting C++/CLI native class (C4679)

I have a public ref class in a C++/CLI assembly (MyAssembly) containing a public static method that accepts native parameters.
#pragma make_public(nativeTypeA)
namespace namespaceA
{
public ref class MyClass : namespaceB::MyClass
{
public:
static managedTypeA ^ MethodA(nativeTypeA param);
static managedTypeB ^ MethodB(nativeTypeB param);
}
}
I would like to expose this method to another C++/CLI assembly. The managed assembly compiles fine but the assembly that references it (CallingAssembly) generates the following warning for MethodB:
warning C4679: 'namespaceA::MyClass::MethodB' : could not import member
This diagnostic occurred while importing type 'namespaceA::MyClass ' from assembly 'MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
I cannot use make_public on nativeTypeB because it is a typedef of a templated class, however, I am using make_public for non-templated native types (e.g. nativeTypeA) and it works (i.e. no C4679 when compiling CallingAssembly). Instead of using make_public, I have declared the native class public and used __declspec(dllexport) in the native header via preprocessor directives as suggested in this post. It was also necessary to conditionally exclude the "public" modifier (via CLR_ACCESS_MODIFIER) as the class is also included in other native projects:
#ifdef MANAGED
#define CLR_ACCESS_MODIFIER public
#ifdef MYASSEMBLY_DEF
#define MYASSEMBLY_LINKAGE __declspec(dllexport)
#else
#define MYASSEMBLY_LINKAGE __declspec(dllimport)
#endif
#else
#define MYASSEMBLY_LINKAGE
#define CLR_ACCESS_MODIFIER
#endif
template<>
CLR_ACCESS_MODIFIER class MYASSEMBLY_LINKAGE nativeTypeB<TT> : public nativeTypeB_base<TT> {
...
}
I have also done this for the base class of nativeTypeB (necessary in order to compile), and its typedef:
typedef public nativeTypeB<TT> MYASSEMBLY_LINKAGE nativeTypeB;
I'm not sure whether the line above is necessary, but C4679 still occurs either way.
I've done the usual checks: the MANAGED preprocessor directive is defined both projects; MYASSEMBLY_DEF is defined in MyAssembly; and I have added a reference to MyAssembly in CallingAssembly as well as MyAssembly.lib to its link line. The project build order is correct and there are no missing dependencies but I am still getting C4679.
I could change the interface to accept non-templated types but I don't really want to do this as it will lead to code bloat and is less elegant. This post mentions that the normal use of "public" in my native class should work.
Can anyone help?
Thanks in advance!
Passing objects of native classes across DLL boundaries has never been a good idea, because it's so very easy to violate the One Definition Rule.
C++/CLI does nothing to help this, instead it provides the ability to generate managed types which are specifically designed for sharing across assemblies. It also prevents you from courting disaster (ODR violations) by sharing native types. You can use the make_public pragma to override this, but with restrictions (such as no templates).
The better way to share native types is via COM-style interfaces.

How to dynamically auto-register C function so it could be available through the whole project without any imports/headers/externs/.pch-files?

In my project I have an doSomething.m and soSomething.h files with the only C function:
void doSomething() {
}
The first question: what should I do to make this function accessible from any place in my code without needing to import any headers?
Note: I guess that to solve this problem the doSomething.h file is not needed at all, but its presence/absence is not a restriction.
I have the following pieces of knowledge but I can't have the whole picture of what is needed:
I can use some another function with attribute((constructor)) that will be run at compilation runtime and it could do some manipulations to register doSomething;
_class_addMethod_ adds methods on "runtime". But I don't know how to resolve "the class of global namespace";
NSObject's + load method but it is not relevant here.
The second tricky question on top of the first: when I will have an answer to the first question, how can I then prevent "Implicit declaration of function 'doSomething' is invalid in C99" exactly for the function doSomething and not for the all others?
UPDATE: I forgot to exclude from the consideration the following options:
.pch file, global headers
The files where I want to use doSomething method should not contain any additional declarations like extern void doSomething()
Well you cant really make it so you dont have to import a header, what you can do however is add the include into your pre compile header
Look in the "Supporting Files" folder in your project.
you will see a file like thise
<ProjectName>-prefix.pch
add your import at the bottom of this file. and every file will then have all the imports added here.
Note
I use Xcode
I guess if your using another IDE such as for GnuStep you would likely have another place similar. I dont know how the other IDE's work.
In the file where you want to use it, import it:
extern void doSomething (void);

Adding a C++ Header to Objective-C project

I've got a strange error working with Photoshop connection API in OSx.
I need to include the header of a cpp file to my project... I start from the adobe example and I included the code in this way:
#include "PSCryptor.h"
which contains the PSCryptor class :
class PSCryptor
{
public:
...
As soon as i try to use PSCrypor object, like with this code
static PSCryptor *sPSCryptor = NULL;
I get this error:
Unknown type name 'class'; did you mean 'Class'?
Could you help me to understand which is my error?
The file is being included in Objective-C files — that is, they have the extension ".m" or they are specifically configured to be compiled as Objective-C (probably the former). Thus, the compiler tries to interpret the code as Objective-C, but C++ is not valid Objective-C, so it complains.
What you need to do is use Objective-C++ instead. Simple fix: change the extension of the files that use that header from ".m" to ".mm".

Objective-c obfuscation of methods works in DEBUG but crashes in RELEASE

I made a xcode project where i did some security stuff and they asked me to obfuscate the method names
like so
#define specialMethod a9328238
+(void) specialMethod
{
// do security stuff
}
i made a .framework library from the project ( project A ) and included it into another project ( project B ).
but when i run (project B) with a Release build configuration it always crashes like so.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[SecurityClass a9328238]: unrecognized selector sent to class 0x337cc4'
so it crashes when it tries to acces the method.
But when i run (project B) it with a Debug build configuration it runs smooth
(i have kept all my build configuration settings as default)
Where have you placed the #define for obfuscation ? Is it in the header file (.h) or in the implementation file (.m) of the framework ?
For the obfuscation to be effective, it must be placed in a file that is both included by the implementation and the caller.
You can also check that the pre-processing is ok by inspecting the pre-processed file. Select the implementation file and go to the menu Product > Generate Output > Generate Preprocessed File (you can select the configuration at the bottom of the screen).
My hunch is the #define location/visibility as well.
But you may want to consider this from another angle. You could change:
#define specialMethod a9328238
+(void) specialMethod
{
// do security stuff
}
to:
#interface SecurityClass : NSObject
// private obfuscated interface:
+ (void)a9328238;
// {
// do security stuff in a9328238's definition
// }
#end
// here is the public interface:
static inline void SecurityClass_LogIn() {
[SecurityClass a9328238];
}
dropping #define altogether.
In use:
SecurityClass_LogIn();
…
Since this is a class method, you could write an obfuscated function wrapped in a human readable inline instead. A well crafted C implementation will be much more difficult to pick apart than objc.
A more complete example would help us narrow down the possibilities.
Also verify there are no warnings -- the compiler may warn you if you have called an undeclared selector. It's possible that the method is called where the #define is not visible in other cases.
It seems that the executable which imports the obfuscated framework tries to access the non-obfuscated methods.
You should check the symbols in the framework. Use nm on the static library in the framework to see the exported symbols (marked with a 't'). Make sure the symbols are obfuscated.
If you've wrapped everything into a framework, have you made sure that the appropriate headers are exposed outside of the framework? Headers inside a framework aren't exposed the same way as normal files are. Go to your Project->Build Phases, in the bottom right you should see "Add Copy Headers". This will add a new section in your build phases. Inside this section, click the "+" and the headers that define your method names.