Reputation: 5492
There are some similar questions on SO but I can't seem to find quite what I'm looking for.
There is a C# library (OpenCVSharp) declaring an overloaded method like this:
public static void CalcHist(Mat[] images,
int[] channels, InputArray mask,
OutputArray hist, int dims, int[] histSize,
Rangef[] ranges, bool uniform = true, bool accumulate = false)
{
....
}
public static void CalcHist(Mat[] images,
int[] channels, InputArray mask,
OutputArray hist, int dims, int[] histSize,
float[][] ranges, bool uniform = true, bool accumulate = false)
{
....
}
i.e. varying only by the type of the "ranges" parameter.
I can't seem to call this method, even when using tupled argument style, including the optional parameters and adding a whole bunch of type annotations:
let images = [|new Mat()|]
let hist = OutputArray.Create(new Mat());
let hdims = [|256|];
let ranges = [| new Rangef(0.f,256.f) |];
Cv2.CalcHist<Mat [] * int [] * InputArray * OutputArray * int * int [] * Rangef [] * bool * bool>
(images,
[|0|],
null,
hist,
1,
hdims,
ranges,
true,
false)
The error is "Error 4 The member or object constructor 'CalcHist' taking 9 arguments are not accessible from this code location. All accessible versions of method 'CalcHist' take 9 arguments"
Is there some way I can call this method from F#?
Upvotes: 4
Views: 883
Reputation: 80915
The syntax you have chosen to specify the types of arguments does not actually work for specifying types of arguments. That syntax is for specifying generic arguments of generic functions or types:
let imGeneric<'t, 'u> (x: 't, y: 'u) = ...
let callGeneric = imGeneric<int, string> (5, "abc")
But of course, most of the time, F# compiler can infer generic arguments for you, so you don't really need to explicitly specify them that often:
let imGeneric (x, y) = ...
let callGeneric = imGeneric (5, "abc")
Your Cv2.CalcHist
method is not generic. Remove generic arguments, and it should work just fine:
Cv2.CalcHist( images, [|0|], null, hist, 1, hdims, ranges, true, false )
The above works, because the compiler already knows that ranges
has type Rangef []
, so it's able to choose the correct overload without you doing any extra work.
But sometimes it is really necessary to explicitly specify types of some (or all) arguments. In these cases, you can specify types right in place:
Cv2.CalcHist(
images, [|0|], null, hist, 1, hdims,
(ranges : Rangef []),
true, false )
Note the extra parentheses around (ranges : Rangef [])
. Without them, the type annotation will apply not just to ranges
, but to the whole tuple of images, [|0|], null, hist, 1, hdims, ranges
, which will cause an compile-time error, because such tuple clearly cannot have type Rangef []
.
Alternatively, you can fix the type of your values at any point before the call:
let ranges: Rangef [] = getRanges()
Cv2.CalcHist( images, [|0|], null, hist, 1, hdims, ranges, true, false )
This will have the same effect. The compiler really only needs to know the type, it doesn't care much where exactly it's defined, as long as it's before the point where it's needed.
Upvotes: 5