|
Great article (and my code does stink)
Below, for convenience, I made a copy of your code for method 1 (automatic way). I see that in the C# version an object named "pNumbers" is passed in the call rather than the "numbers" array. The VB code passes the "numbers" array itself. Is pNumbers another array or is it a pointer or is it a typo? Also, is "unsafe" required in the C# version?
C#
public int ArrayAutomatic() {
int dim=1000;
int[] numbers=new int[dim];
...
int sum=SumArray(pNumbers, dim);
return sum;
}
[DllImport("native.dll")]
unsafe public static extern int SumArray(int[] numbers, int count);
VB
Public Function ArrayAutomatic() As Integer
Dim dime As Integer = 1000
Dim numbers(dime) As Integer
...
Dim sum As Integer = SumArray(numbers, dime)
Return sum
End Function
Declare Auto Function SumArray Lib "NativeC.dll" (ByVal numbers As Integer(), ByVal count As Integer) As Integer
With your help I am able to get the array using C# by using a literal translation of your VB example:
C++
extern "C" int __declspec(dllexport) __stdcall ret_arr(float returnArray[])
{
returnArray[0] = 5;
returnArray[1] =10;
return 1;
}
C#
[DllImport("CudaFft.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ret_arr")]
public static extern int ret_arr(float[] retArray);
private void test()
{
float[] retArray = new float[2];
int ans = ret_arr(retArray);
}
It works but it may still stink. Am I on my way?
|
|
|
|
|
You're right, there's a typo in my article, nobody ever noticed, myself including. I will fix it.
int sum=SumArray(numbers, dim); is what it should be in automatic mode.
Thanks for pointing this out.
Your code is fine. One suggestion: whenever possible, also pass the length as a separate parameter, that way your native code can be confident about how much data it can safely read and/or write (automatic mode turns the array reference into a simple pointer, so all size info isn't passed on). That is what the dim parameter is doing in my example. As always, reading memory locations you're not supposed to read may cause an exception, writing beyond the boundaries most probably will cause an exception.
|
|
|
|
|
Your article is very good. I have been researching how to pass arrays to unmanaged functions for a few days and, although there is plenty out there, your explanation was concise and complete and the implementation was simple and elegant.
I gave your website an "excellent" WOT rating. http://www.mywot.com/en/scorecard/perceler.com
|
|
|
|
|
Thanks. I'm glad you liked it.
FWIW: next year, I'll spend time to write part 2, on passing structures.
|
|
|
|
|
If you're planning to use CUDA, why not just use existing .NET bindings instead of your own? (CUDAfy.NET for example?)
|
|
|
|
|
Hi,
Although CUDA.NET has had CUFFT capabilities since at least v2.0, I was not able to fly CUDA.NET in VS 2008 Express (for CUFFT anyway) - probably just my stupidity. Learning how to communicate with unmanaged code has been a good experience. Later, I'll probably revisit an open source library approach because I'll probably get better performance. There are a couple other libraries out there (GPU.NET and MS Accelerator) but the FFT capability isn't implemented yet.
|
|
|
|
|
OK, senior moment. I'll look more closely at CUDAfy.net.
|
|
|
|
|
If I'm given a string in the format: aaaaaa.bbb.ccc.ddd....qqq. Basically the string is words seperated by a single dot. Words can be any length and the string can have any number of segments. Think C# namespace.
Now, I want to remove the last segment... so I want to take:
A.B.C.WpfApplication3.Application
and get
A.B.C.WpfApplication3
I know you just reverse find the last . and trim the string there, but I'm wondering if there are any cool tricks with split / join, linq extensions, etc?
Bored, so trying to come up with a one liner ... can't make any assumption that the last part of the string will be .Application either .
But the input IS going to be a namespace + class name. (this.GetType().ToString()).
|
|
|
|
|
System.IO.Path.GetFileNameWithoutExtension ( "A.B.C.WpfApplication3.Application" )
(Only if it satisfies the rules for a path of course.)
I'd likely use a Regex.
SledgeHammer01 wrote: reverse find the last .
Or use LastIndexOf ?
|
|
|
|
|
Hmm... came up with myself:
s = s.Replace(s.Split('.').Last(), String.Empty);
s = s.Remove(s.LastIndexOf('.'));
saw one thing on stackoverflow where the guy suggested:
.Split().Reverse().Skip(1).Reverse().Join()
that ones kind of clever... but I guess the 2nd one I mentioned will do.
|
|
|
|
|
I certainly wouldn't use Split or Reverse.
Substring and LastIndexOf maybe, but what if you get something like:
System.Collections.Generic.List<System.Int32> ?
|
|
|
|
|
Well, the goal of this is to be able to access the application user settings at runtime without having the developer do anything.
So for example, in my prior example, I have:
A.B.C.WpfApplication3.App
that class derives from my "ApplicationEx" class.
So in ApplicationExs constructor, I want to mess around with A.B.C.WpfApplication3.Properties.Settings.Default and do stuff with the settings. So I kind of need to figure out the namespace of the settings class at runtime so I can use reflection. I guess there can be cases where they don't match up like that... but having the user pass in the type or namespace string seems kinda cheezy.
|
|
|
|
|
SledgeHammer01 wrote: .Split().Reverse().Skip(1).Reverse().Join()
I think that falls under the just because you can doesn't mean you should category.
No comment
|
|
|
|
|
I wouldn't recommend it, but if you want to play with some code, here you go:
string result = (from pos in new int[] { (str ?? string.Empty).LastIndexOf('.') } select (str ?? string.Empty).Substring(0, pos >= 0 ? pos : 0)).First();
One line, only calls LastIndexOf once, handles a null input string, and handles the case that a period doesn't exist in the string.
Somebody in an online forum wrote: INTJs never really joke. They make a point. The joke is just a gift wrapper.
|
|
|
|
|
AspDotNetDev wrote: handles a null input string
You mean it "quietly goes on about its business"?
|
|
|
|
|
Some tweaks:
string result = string.IsNullOrEmpty(str) ? str : (from pos in new int[] { str.LastIndexOf('.') } select str.Substring(0, pos >= 0 ? pos : str.Length)).First();
Somebody in an online forum wrote: INTJs never really joke. They make a point. The joke is just a gift wrapper.
|
|
|
|
|
How about: Regex.Replace("A.B.C.WpfApplication3.Application", "\.\w*$", "")
Ok it's oldschool, but still cool right? (right?)
Or if you want to allow weird chars: Regex.Replace("A.B.C.WpfApplication3.Application", "\.[^\.]*$", "")
modified 16-Dec-11 18:34pm.
|
|
|
|
|
I suspect those will remove more text than you think. Maybe toss a ^ or $ at the end (whichever of those matches the end of a string).
Somebody in an online forum wrote: INTJs never really joke. They make a point. The joke is just a gift wrapper.
|
|
|
|
|
No they match exactly the right amount.. just not at the right place.
|
|
|
|
|
He has the $ at the end -- think of the money shot.
|
|
|
|
|
Strangely, he also has [modified] at the end. Weird.
Somebody in an online forum wrote: INTJs never really joke. They make a point. The joke is just a gift wrapper.
|
|
|
|
|
I can see you've got lots of solutions for the "trimming the string" task, but what I am curious about is:
Once you have the final string, how are you going to cast/transmute that into a usable reference to the current running application's settings: in your own words: "access the application user settings at runtime without having the developer do anything" ?
If you are the creator of the Application, isn't it possible for you, in the app initialization code to set a reference to the App's settings, to use later ?
best, Bill
When I consider the brief span of my life, swallowed up in the eternity before and after, the little space which I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which knows me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then. Blaise Pascal
|
|
|
|
|
I won't bore you with the full details of why I'm trying to do this because that'll be a long winded explanation . To summarize it in one sentence: I'm writing an application framework library and I currently instruct users to "copy these 4 lines into your startup code and modify the namespace to handle this specific scenario".
The code they copy is basically 4 lines that look something like:
WpfApplication3.Properties.Settings.Default...
I'd like to update my framework so they no longer have to do that. I already have an 'ApplicationEx' class that they derive from.
So, what I do is, in the ApplicationEx constructor, I do:
string type = this.GetType().ToString(); // this is going to give me something like "WpfApplication3.App"
I then take "WpfApplication3.App" and use the string manipulation stuff above to get the string "WpfApplication3.Properties.Settings".
I then do:
Type t = Type.GetType("WpfApplication3.Properties.Settings"); // Type.GetType is a static method in the Type class
that gives me the type of the settings class. The settings class (as generated in VS) has a static public property called Default that returns the instance, so I simply use reflection to get the PropertyInfo of that property and invoke the getter and viola... I've got an ApplicationSettingsBase reference to the settings class .
|
|
|
|
|
+5 Enjoyed the explanation, and that's clever code
When I consider the brief span of my life, swallowed up in the eternity before and after, the little space which I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which knows me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then. Blaise Pascal
|
|
|
|
|
Hi,
I have tried to deploy my web application (VS2010 + C#) by adding the project output and building a msi setup. But, I want to do these steps through command prompt. Our command scripts will do all the stpes to deploy in server.
That command prompt scripts should do the following things
1. Getting latest version of my solution
2. Adding web deployment project and adding project outputs there
3. Building and deploying in a server..
How to do these things thorugh command prompt only?
Thanks in advance.
Balasubramanian K.
|
|
|
|