Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 9 months ago.
Improve this question
I am trying to call a C function from Swift , but I do not know exactly how to define variables to pass parameters. This is the function declaration:
/* Function Declarations */
extern void compute_feature_set(const double input[11025],
double M_data[], int M_size[2],
double D_data[], int D_size[2],
double DD_data[],
int DD_size[2],
double VT[10], double *mp,
double r_42[42], double *fM);
The data is an array of floats. So I tried :
let s = data.compactMap{ Double($0)}
var mSize = Array<Int32>(repeating:Int32(0.0), count:2)
var dSize = Array<Int32>(repeating:Int32(0.0), count:2)
var dD_Size = Array<Int32>(repeating:Int32(0.0), count:2)
var mData = Array<Double>(repeating:0.0, count:48)
var dData = Array<Double>(repeating:0.0, count:48)
var dD_Data = Array<Double>(repeating:0.0, count:48)
var vt = Array<Double>(repeating:0.0, count:10)
var mp = Double(0.0)
var r = Array<Double>(repeating:0.0, count:42)
var fM = Double(0)
compute_feature_set(s, &cout, &mSize, &vx, &dSize, &dD_Data, &dD_Size, &vcta, &mp, &r, &fM)
When I run the code in Clion with the following function it works fine and the output matches the expected values:
static void main_compute_feature_set(void)
{
static double dv[11025];
double DD_data[48];
double D_data[48];
double M_data[48];
double r_42[42];
double VT[10];
double fM;
double mp;
int DD_size[2];
int D_size[2];
int M_size[2];
/* Initialize function 'compute_feature_set' input arguments. */
/* Initialize function input argument 'input'. */
/* Call the entry-point 'compute_feature_set'. */
argInit_11025x1_real_T(dv);
compute_feature_set(dv, M_data, M_size, D_data, D_size,
DD_data, Dd_size, VT,
&mp, r_42, &fM);
}
However, when I run my implementation in Swift, I get very different results.
You could try passing pointers of the Arrays, rather than the Arrays directly.
Using Imported C Functions in Swift | Apple Developer Documentation
Call Functions with Pointer Parameters
Whenever possible, Swift avoids giving you direct access to pointers. When importing C function parameters, however, Swift maps pointer parameters to standard library pointer types.
The following tables use Type as a placeholder type name to indicate syntax for the mappings.
For return types, variables, and arguments, the following mappings apply:
C Syntax
Swift Syntax
const Type *
UnsafePointer<Type>
Type *
UnsafeMutablePointer<Type>
double[] is pretty much equivalent to double * in this case.
Looks like the problem with your code is passing data to your function. You use compactMap to make an Array of Double and then pass the pointer of this array. But Array and Double are struct in Swift so you pass the pointer of struct with structs instead of array of double values.
To convert your data to array of bytes you should use withUnsafeBytes e.g.:
Swift:
let data = Data([0xaa, 0xbb, 0xcc, 0xdd])
data.withUnsafeBytes {
passData($0)
}
C/ObjC:
void passData(const double input[11025]) {
NSLog(#"%x", input[0]); // Prints: ddccbbaa
}
I’m just learning swift and can’t seem to figure out a problem.
I’ve tried changing the function text but nothing seems to be working
func multiply(_ a: Double, _ b: Double) -> Double {
a * b
}
solution.swift:2:7: warning: result of operator '*' is unused
a * b
~ ^ ~ solution.swift:3:1: error: missing return in a function expected to return 'Double' } ^
That code uses the new feature introduced in Swift 5.1 - implicit returns from single expression functions. (New features in Swift 5.1)
Make sure you are using Swift 5.1/Xcode 11. If you are not, you have to write return:
func multiply(_ a: Double, _ b: Double) -> Double {
return a * b
}
)
I have updated a "Workout Object" to have both a minimum and maximum number of reps.
When I've been hardcoding the lower bound in a playground, I've been using :
let numberOfExercises = Int(arc4random_uniform(4) + 3)
When I try to use variables in a function/with a class object I get an error of "+'is unavailable: Please use explicit type conversions or Strideable methods for mixed-type arithmetics" e.g. here ...
class ExerciseGeneratorObject: Object {
#objc dynamic var name = ""
#objc dynamic var minReps = 0
#objc dynamic var maxReps = 0
convenience init(name: String, minReps: Int, maxReps: Int) {
self.init()
self.name = name
self.minReps = minReps
self.maxReps = maxReps
}
func generateExercise() -> WorkoutExercise {
return WorkoutExercise(
name: name,
//get error on this line...
reps: Int(arc4random_uniform(UInt32(maxReps))+minReps)
)
}
}
There is an answer here + is unavailable: Please use explicit type conversions or Strideable methods for mixed-type arithmetics but that method is already using so don't see how it's applicable here.
Also here '+' is deprecated: Mixed-type addition is deprecated in Swift 3.1 but again think this is a different problem
'+' is unavailable: Please use explicit type conversions or Strideable methods for mixed-type arithmetics.
Example:
let a: UInt32 = 4
let b = 3
let result = a + b //error
Basically means you can't add mixed-types.
In your case when you do arc4random_uniform(UInt32(maxReps)) + minReps, arc4random_uniform() returns a UInt32 which cannot be added to minReps because that's an Int.
Solution:
Update your parenthesis:
let numberOfExercises = Int(arc4random_uniform(UInt32(maxReps))) + minReps
Here Int(arc4random_uniform(UInt32(maxReps))) gives an Int that we can add to the minReps Int.
BTW, the following works out-of-the-box:
let numberOfExercises = Int(arc4random_uniform(4) + 3)
Because of Swift's automatic type inference. Basically it just went ahead with UInt32 without bothering you. That is... until you give it explicit mixed types.
In swift 2.3 I had this working simple piece of code:
let joinedString = partOne! + PartTwo! + PartThree! + PartFour!
Now with the conversion to swift 3 I've been bashing my head in over about 24 errors out of the blue with the most vague explanations.. This is one of them:
The same line of code gives error:
Ambiguous reference to member '+'
However if I split them up like so:
let OneAndTwo = partOne! + partTwo!
let ThreeAndFour = partThree! + PartFour!
let joinedString = OneAndTwo + ThreeAndFour
This works... Did they remove linking multiple strings like this or is it buggy? Seems like the compiler thinks the '+' is a variable or something else named the same?
EDIT:
Even though it's another error this seems to be related to: This Question
Also crashes once you go upwards of 2 optional strings. I guess optional binding is the way to go then. Seems like this bug has been there for quite some time.
This seems like a bug and I'll investigate further. If we simulate the behaviour of ! with another operator it works just fine:
postfix operator |! {}
postfix func |! <T>(rhs: T?) -> T {
return rhs!
}
let s1: String? = "Hello"
let s2: String? = " "
let s3: String? = "World"
let joined = s1|! + s2|! + s3|! // "Hello World"
For example, I have the following code:
let numberOfBlocks = 3
let blockWidth = SKSpriteNode(imageNamed: "image.png").size.width
let padding = 20.0
let offsetX : Float = (self.frame.size.width - (blockWidth * numberOfBlocks + padding * (numberOfBlocks-1))) / 2
I got the error:
'Double' is not convertible to 'UInt8'
Is there a way to implicitly convert the data type (maybe only for primitive data type)?
Edit:
I know how to do the explicit conversion by using constructor of particular type as Iducool suggested. But it's not a big help to my question because we even don't know where to add the conversions. I simplified my expression in playground:
The problem is in "padding" variable, the error message is
'Double' is not convertible to 'UInt8'.
So I did the conversion:
Then the problem is in "blockWidth" variable now.
I added the conversion again:
And error message is:
Type 'UInt8' does not conform to protocol 'FloatLiteralCovertible'
The final working expression is:
Is it simple and swift? I don't think so.
There is no implicitly cast in Swift.
Easy way of conversion in swift is using constructor of particular type.
Like if you want to get Float from double then you can use Float(doubleValue) and Same way if you want to convert float to integer then you can use Int(floatValue).
In your case:
let intValue = UInt8(doubleValue)
Beware that you will lose any value after the decimal point. So, choose a better way. Above conversion is just to help you in understanding.
Note that Swift always chooses Double (rather than Float) when inferring the type of floating-point numbers.
Swift doesn't support implicitly cast anymore in Xcode6 GM. Following answer only apply to Xcode6 beta version.
I don't want to talk about implicitly cast is good or bad, but you can have it if you really want with __conversion()
e.g. If you need UInt8 and Int be able to convert from Double
extension Double {
func __conversion() -> UInt8 { return UInt8(self) }
func __conversion() -> Int { return Int(self) }
// add more if you need to
}
xcrun swift
Welcome to Swift! Type :help for assistance.
1> extension Double {
2. func __conversion() -> UInt8 { return UInt8(self) }
3. }
4> var d = 1.0
d: Double = 1
5> var u8 : UInt8 = d
u8: UInt8 = 1
6>
Note: I won't put this in my production code. I only want to point out it if possible but not recommending it.
using bridgeToObjectiveC() method you can call the methods provided in Objective - C to convert from one primitive data type to another for e.g.
variable_name.bridgeToObjectiveC().intValue
will convert that variable named variable_name to integer
Implicit conversion is possible but with literals only and some conversions are available from the box e.g. Int -> Double:
let a = 3 // Int
let b = 100.5 // Double
// Doesn't work with variables
let c = a * b // Error: Binary operator '*' cannot be applied to operands of type 'Int' and 'Double'
// But this works, because Int(3) literal converts to Double(3.0) implicitly
let d = 3 * b // 301.5
If you want to make backward conversion Double -> Int you should extend Int with ExpressibleByFloatLiteral:
extension Int: ExpressibleByFloatLiteral {
public init(floatLiteral value: Double) {
self.init(value)
}
}
// Double(100.5) converts to Int(100)
let e = a * 100.5 // 300
Even more it's possible to implicitly convert to any type from literals, for instance String -> URLRequest:
extension URLRequest: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self.init(url: URL(string: value)!)
}
}
let request: URLRequest = "https://www.google.com"