I want to wrap a c++ pointer field to property in CLI, here is my code:
class NativeClass
{
public:
int* nativeApointer;
}
ref class ManagedClass
{
NativeClass* thisClass
property int^ A
{
int^ get()
{
return thisClass->nativeApointer
}
}
}
compiler noticed errror, so how did convert unmanaged pointer to interior pointer?
Related
#objc public class A: NSObject
{
public func getSomething() -> Something
{
return Something()
}
}
#objc public class B: A{
override public func getSomething() -> SomethingGood
{
return SomethingGood()
}
}
#objc public class C: A{
...
}
#objc public class Something: NSObject{
var name: String=“”
}
#objc public class SomethingGood: Something{
var type_id: Int = 0
}
Swift compiler shows incompatible types for class B's override function. How do I implement the above? I have tried to use Generics but they are not available for Objective-C developer once the library is built.
I want to be able to use:
A.getSomething() and C.getSomething() to return an object of Something
And B.getSomething() to return an object of SomethingGood.
And I don't want to get two same named function which is func getSomething() for B with two different return types.
Any idea?
The code is used in a static library written in Swift. Once the library is compiled, it should be available to both swift and objective-c.
You can't change the return type, or it wouldn't be an override. You can still return SomethingGood in this case, just your function declaration can't show the return type as that.
#objc public class B: A{
override public func getSomething() -> Something
{
return SomethingGood()
}
// now whereever you're calling this, if you know it's SomethingGood, you can cast it
if let somethingGood = b.getSomething() as? SomethingGood {
// do something good
}
I have wrapper classes contaning COM pointers (or smart pointers) to different interfaces.
INTEND:
Some COM classes can be obtained from various other COM interfaces, and I want to make a template constructor with variadic types, which would allow passing arguments only of appropriate types.
something like:
template <class T, class = typename
std::enable_if<std::is_base_of<IUnknown, T>::value>::type, class ... Types>
class WithCOMptrbase
{
protected:
T* ptr_;
public:
//construct smart pointer by copy
WithCOMptrbase(T* ptr, bool AddRef = false)
: ptr_(ptr)
{
if (AddRef) ptr_->AddRef();
}
/*construct a smart pointer by querying an interface from an argument of
a type which is the same as one of the variadics*/
template <class TypeOther, class = typename
std::enable_if<syd::is_same<Types... , TypeOther>::value... ||
...>::type> /*there needs to be a proper version*/
WithCOMptrbase(TypeOther* ptr)
: ptr_(cQueryInterface<T>(ptr))
{}
//other methods
};
helper function:
template <class U, class = typename
std::enable_if<std::is_base_of<IUnknown, U>::value>::type>
T* cQueryInterface<T>(U *ptr)
{
T* out;
HRESULT hr = ptr->QueryInterface(__uuidof(T), (void**)&out);
if (!SUCCEEED(hr)) throw _com_error(hr);
return out;
}
Therefore, I will define my wrapper class
class WrapperClass : protected WithCOMptrbase<IThis, IInterface1, IInterface2, IInterface3>
{
//methods
};
So far I have found this thread:
How to make a variadic is_same?
but it is only about structs, not functions.
My goal is to limit the possibility of passing inapproprtiate Interface pointer, hence not to deal with wrong interface errors at runtime.
UPDATE:
Since Composition is preferable over inheritance, I've done some rethinking and decided to use a template function rather than a template class. So far I've managed to combine given answers and came up with this:
template <bool S, class Out, class Other, typename
std::enable_if<S>::type* = nullptr>
//copy-construct Smart Pointer for same Interfaces
WComPtr<Out> WFilterSame(const WComPtr<Other>& pOther)
{
return WComPtr<Out>(pOther);
}
template <bool S, class Out, class Other, typename
std::enable_if<!S>::type* = nullptr>
//Query Interface if differ
WComPtr<Out> WFilterSame(const WComPtr<Other>& pOther)
{
return pOther.QueryInterface<Out>();
}
template <class Out, class ... Permitted, class Other>
WComPtr<Out> WFilterComInterfPtr(const WComPtr<Other>& pOther)
{
static_assert(std::is_same<Out, Other>::value ||
(std::is_same<Permitted, Other>::value || ...),
"Interface is not supported.");
return WFilterSame<std::is_same<Out, Other>::value, Out>(pOther);
}
Now I can define a constructor of my COM wrapper class:
class WComClass
{
private:
WComPtr<Interface> pComPtr_; //My Smart COM pointer
template <class Other>
WComPtr<Interface> WFilter(const WComPtr<Other>& pOther)
{
return WFilterComInterfPtr<Interface, IAllowed1, IAllowed2>(pOther);
}
public:
template <class Other>
WComClass(const WComPtr<Other>& pOther)
: pComPtr_(WFilter(pOther))
{}
//methods
};
So far it behaved as intended (WFilterComInterfPtr), I don't expect it to fail in the wrapper class costructor.
Try with
template <class TypeOther, class =
std::enable_if_t<(std::is_same_v<Types, TypeOther> || ...)>>
WithCOMptrbase(TypeOther* ptr)
: ptr_(cQueryInterface<T>(ptr))
{}
I mean... you're using three ellipsis instead of one (remove the ellipsis after ::value and the one after Types) and you need an additional couple of parentheses.
Off topic: are you sure that works
template <class T, class ... Types, class = typename
std::enable_if<std::is_base_of<IUnknown, T>::value>::type>
class WithCOMptrbase
?
SFINAE through a default type after a variadic list?
How about CRTP to avoid some template:
template <typename Base, typename T>
class Impl
{
public:
Impl() = default;
explicit Impl(T*) { static_cast<Base*>(this)->ptr_ = cQueryInterface<T>(ptr); }
};
template <class T, class ... Ts>
class WithCOMptrbase : private Impl<WithCOMptrbase<T, Ts...>, Ts>...
{
static_assert(std::is_base_of<IUnknown, T>::value);
static_assert((std::is_base_of<IUnknown, Ts>::value && ...));
template <typename, typename> friend struct Impl; // We don't have variadic friend :/
protected:
T* ptr_ = nullptr;
public:
using Impl<WithCOMptrbase, Ts>::Impl...;
//construct smart pointer by copy
explicit WithCOMptrbase(T* ptr, bool AddRef = false) : ptr_(ptr)
{
if (AddRef) ptr_->AddRef();
}
//other methods
};
I have a mixed project and came across an interesting issue.
There's an enum, defined in obj-c
typedef NS_ENUM (NSUInteger, ABCCategory) {
ABCCategoryFirst,
ABCCategorySecond
};
Next, there's a swift file where an extension is defined
extension ABCCategory: RawRepresentable {
public typealias RawValue = String
public init(rawValue: RawValue) {
switch rawValue {
case "first":
self = .first
case "second":
self = .second
default:
self = .first
}
}
public var rawValue: RawValue {
get {
switch self {
case .first:
return "first"
case .second:
return "second"
}
}
}
}
Everything works fine in the Debug configuration, but when I switch to Release it does not build, saying: Invalid redeclaration of 'rawValue'
I've tried removing typealias, replacing RawValue with String (so the protocol could implicitly guess the value), making constructor optional as in the protocol (and implicitly unwrapped optional also) - no go.
I do understand that extending an Int enum with string is a bit weird, but why it stops building in Release and working absolutely perfect in Debug?
Is there some different mechanism of treating enums/classes/extensions for Release configuration?
The raw value syntax for enums in Swift is “just” a shorthand for conformance to the RawRepresentable protocol. It’s easy to add this manually if you want to use otherwise unsupported types as raw values.
Source
I'm not sure why it works in debug because when you create a typed enum you are already 'conforming' to RawRepresentable. So when you create an NS_ENUM it is imported in to swift like so:
public enum ABCCategory : UInt {
case first
case second
}
Meaning that it already conforms to RawRepresentable. The fix can be achieved two ways, one in Swift and in Objective-C
In Swift we just remove the RawRepresentable and change rawValue to stringValue, and RawValue to String:
extension ABCCategory {
var stringValue: String {
switch self {
case .first: return "first"
case .second: return "second"
}
}
init(_ value: String) {
switch value {
case "first":
self = .first
case "second":
self = .second
default:
self = .first
}
}
}
Or you could just change the Objective-C to use NS_TYPED_ENUM. Some info here. However this will change your enum to a struct
.h
typedef NSString *ABCCategory NS_TYPED_ENUM;
extern ABCCategory const ABCCategoryFirst;
extern ABCCategory const ABCCategorySecond;
.m
ABCCategory const ABCCategoryFirst = #"first";
ABCCategory const ABCCategorySecond = #"second";
This will be imported by swift like so:
public struct ABCCategory : Hashable, Equatable, RawRepresentable {
public init(rawValue: String)
}
public static let first: ABCCategory
public static let second: ABCCategory
MMCondition is a protocol defined in Swift, but interoperates with Objective-C (annotated with #objc).
#objc public protocol MMCondition {
static var name: String { get }
static var isMutuallyExclusive: Bool { get }
}
I have the following code:
// addCondition cannot be generic as I want it to be accessible from Objective-C as well.
public func addCondition(condition: MMCondition) {
// How do I initialize OperationConditionImplementer here?
let operationCondition = OperationConditionImplementer(condition: condition) // doesn't compile
// Error: Cannot invoke initializer for type 'OperationConditionImplementer<T>' with an argument list of type '(condition: MMCondition)'
// Can I use condition.dynamicType to init OperationConditionImplementer somehow?
}
struct OperationConditionImplementer<T: MMCondition> {
let condition: T
static var name: String {
return "Silent<\(T.name)>"
}
static var isMutuallyExclusive: Bool {
return T.isMutuallyExclusive
}
init(condition: T) {
self.condition = condition
}
}
From Objective-C, you can't use generics as stated in the documentation.
You’ll have access to anything within a class or protocol that’s
marked with the #objc attribute as long as it’s compatible with
Objective-C. This excludes Swift-only features such as those listed
here:
Generics
...
So you need to remove completely the generics code. One possible solution might be:
#objc protocol MMCondition {
static var name: String { get }
static var isMutuallyExclusive: Bool { get }
}
struct OperationConditionImplementer {
let condition: MMCondition
var name: String {
return "Silent<\(condition.dynamicType.name)>"
}
var isMutuallyExclusive: Bool {
return condition.dynamicType.isMutuallyExclusive
}
init(condition: MMCondition) {
self.condition = condition
// Here decide comparing types
if condition.dynamicType === ExampleCondition.self {
print(condition.dynamicType.name)
}
}
}
So for instance, if you try it out in a playground:
class ExampleCondition: NSObject, MMCondition {
static var name: String = "ExampleCondition"
static var isMutuallyExclusive: Bool = false
}
let example = OperationConditionImplementer(condition: ExampleCondition())
You'll see "ExampleCondition" printed.
If you eventually switch to pure Swift, you need to specify T when initializing a OperationConditionImplementer.
You can achieve that defining the addCondition method as:
func addCondition<T: MMCondition>(condition: T) {
let a = OperationConditionImplementer<T>(condition: condition)
}
Since Swift 2.0 instances of generic classes can implement Objective-C protocols. What won't be possible I believe is having a struct implement the protocol. In fact I expect that your protocol may need to inherit from NSObjectProtocol to be usable in Objective-C which would then prevent you from implementing the protocol with structs or enums.
You also rightly mention that you can't access generic functions from Objective-C.
For a concrete example of using a generic to fulfil an Objective-C protocol have a look at this blog post.
I have class with 2 methods
class A
{
void Fun()
{
if(FunRet()>0){///} else {///}
}
int FunRet()
{ return 4;}
};
I want to test Fun() method depend on what FunRet returns. So i want to mock FunRet.
I rather don't want make FunRet as virtual. How I can do that?
You can inject intra-class dependencies. In this case, make Fun accept a value instead of computing it:
class A
{
void Fun(int x)
{
if(x>0){///} else {///}
}
int FunRet()
{ return 4;}
};
Then your tests can pass arbitrary values into Fun(). If you need to enforce correct use, write a public version to expose in your API and a private version for testing:
class A {
public:
void Fun() { return Fun(FunRet()); }
private:
void Fun(int x); // for testing.
};
You could extract the Fun method into a calculator class that implements an interface. You should pass an instance of that interface to class A at constructor.
In testing you could have other classes implementing that interface, that return other values.
This method also have the big advantage, that you seperate the concerns of calculating a value and using the calculated value.
class A {
public:
A (IFunCalc calc) { m_calc = calc; }
void Fun { if calc.FunRet() > 4 ... }
private:
IFunCalc m_calc;
}
class FunCalc : IFunCulc {
public:
int FunRet { return 4; }
}
class FunCalc4Test : IFunCalc {
public:
int FunRet { return 27; }
}
I think you're missing the this pointer.
... if ( this->FunRet() > 0 ) { ...
If you use dependency injection and template your object under test, you can use mock objects without having to use virtual functions.
class AParameters
{
public:
int FunRet()
{ return 4;}
};
class MockAParameters
{
public:
MOCK_METHOD0(FunRet, int());
};
template<class Parameters>
class AImpl
{
public:
AImpl(Parameters& parameters):parameters(parameters){}
void Fun()
{
if(parameters.FunRet()>0){///} else {///}
}
private:
Parameters& parameters;
};
typedef AImpl<AParameters> A;
typedef AImpl<MockAParameters> ATestObject;
void Test::funUsesFunRet()
{
MockAParameters params;
EXPECT_CALL(params, FunRet());
ATestObject object(params);
object.Fun();
}
I believe FunRet is an internal implementation detail of Fun. As a result, Fun does not need to be tested in isolation from FunRet. Just test Fun and don't worry about the fact it calls FunRet.