|
I maybe missing something here, but to my knowledge: there is no such thing as "new unmanaged instance" -- there is just "unmanaged instance". Assuming that you are hosting CLR -- this is an instance. If this is true: then why can't you declare your unmanaged callback functions as exported. And now mark there prototypes in your managed portion as DllImported and call them.
Why this shouldn't work?
Now about "security problem"? As I understand, you are hosting managed code in unmanaged -- therefore, by defenition your application is not secured right from the beginning -- why would you want to enforce security in the middle of execution? Or maybe I'm missing something?...
|
|
|
|
|
Sorry for confusion, to simplify, please think about
applications such as asp.net. IIS probably hosting
those scripts, execute them in its hosted appdomain,
then get their output back to IIS.
I'd like to know how it works.
|
|
|
|
|
He's calling managed code from an unmanaged DLL. How would P/Invoking anything help? At the very least, the managed method he's calling would have to bind to a specific DLL which isn't very modular and is very restrictive.
To the original poster, have you tried creating an instance of a Delegate (it uses an AutoDual interface, which Microsoft always tells you not to use, BTW ) Once you have an instance to that, you should be able to get what you need from there.
Just a thought.
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
I'm seriously confused here.
From what I understand you have the following scenario:
1. Unmanage instance, lets name it (U) is hosting AppDomain and loads managed assembly, lets name it (M);
2. Now (U) calls some fuction or creates a clas or etc. inside of (M);
Original question was: how now (M) can call back fuction(s) inside of (U)?
My answer was:
what stopes you from declaring some entry points in (U) as Exported, through dllexport or .DEF file, and then declaring them in (M) using DllImport Attribute. If above is done, then you can call those entries from (M) directly into (U).
Maybe I didn't understand perfectly the scenario, but from what I understand: "He's NOT calling managed code from an unmanaged DLL", but opposite -- he wants to callback from managed into unmanaged host...
Regards,
Igor
|
|
|
|
|
Right, so he's going to P/Invoke a method from a specific DLL and use that in a managed method to emulate a callback. So, that DLL is the only DLL that can be used for a callback and no DLLs can be used instead. If that managed method isn't careful in its implementation, calling the P/Invoked method when the DLL isn't there could lead to problems like exceptions being thrown. It's restrictive, as I said, and is not modular at all.
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
So, it "could be restrictive, not modualr and etc"... And I'm not arguing with that.
But, the main thing is: "He wants to CALLBACK from MANAGED to UNMANAGED" and therefore P/Invoke could help, which you originally dismissed!
Now, about "restrictive, not modular and etc": Sure if you implement managed callback through DllImport, you basically HARD CODED necessaty of having UNMANAGED Implementation loaded --> and that is why it's not flexible enough. However, that's exactly how P/Invoke works -- You are not questioning necessaty of user32.dll, gdi32.dll and etc. to support CLR OS calls...
Said that: there are ways of performing interpretive P/Invoke, but I thought it's out of the scope of original question.
Regards,
Igor
|
|
|
|
|
No, I get it - completely. P/Invoke could do it, yes, but it is RESTRICTIVE! He has to P/Invoke the unmanaged method in his managed code. Right there, that ties it to a specific DLL and that is the restrictive part. Then, in the managed code, he has to call that P/Invoke'd method. If he assumes that the method was found (i.e., the DLL exporting it is present) and, in fact, it wasn't found, the consequences could be bad if not handled right.
Trust me - I know how P/Invoke works. I get into the meat of .NET and have read all the documentation countless times. All I'm saying is that P/Invoke ties the code to one DLL.
Besides, you're also assuming that he has access to the source of the assembly. What if he's doing something in the .NET assemblies, part of the .NET framework. He can't add an external method and he can't make the message body call the P/Invoke'd method. A wrapper might be possible, but painful. My idea about instantiating a Delegate from unmanaged code (since it implements IDispatch, calling its methods are easy) and passing that to the callback parameter of whatever he's calling. He would still be to have a small assembly (or emit one) that receives the callback. Using your idea in that might work, but hard-coding it into the "target" assembly (if he can even change the assembly) isn't necessarily a good idea. If he can insure that these two assemblies will always be present together and that he doesn't want to ever replace the unmanaged DLL, sure it might work. Frankly, I just don't swing that way because I like to make my code versatile, instead of paying for it later.
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
No question, I absolutely agree with you that the right and reusable way to do this would be to pass IDispatch supported object created in unmanaged part and put logical part of callback into it's Invoke method.
However, I thought, that original poster looks for "simple" and not bnecessarily reusable ways of achieving result. Said that: My feeling is that even with IDispatch solution: at some point you have the same P/Invoke, just implemented by RCW, isn't it? Yes, it would be dynamic, and yes you don't have to implement it. However, you have to inmplement COM objects on unmanaged site.
The only soultion I could think of that doesn't require P/Invoke at some point, would be probably: Creating WinSock port and start listening on it...hehehe
What is better and faster -- I don't know: depends on the project. I don't think that there is better/simplier soultion then just be able to callback as we were always doing in C, but unfortunately that's CLR restrictions.
About your point of making "code versatile" -- that is nice.
|
|
|
|
|
In CLR hosting in unmanaged app, you can invoke methods of hosted managed components in hosted AppDomain via IDispatch, but how can you make callback from hosted component to its unmanaged host, in asynchronous manner?
I browsed several examples of CLR hosting, but they are all simply invoking 1-way method like "hello world" and there's no interaction in them except for synchronous HRESULT.
|
|
|
|
|
Can't you just use PInvoke for that?...
|
|
|
|
|
|
Math Namespace? Give me "qsort" please!...
|
|
|
|
|
igor1960 wrote:
Math Namespace?
System.Math - it's a class, not a namespace.
igor1960 wrote:
"qsort"
"Blessed are the peacemakers, for they shall be called sons of God." - Jesus
"You must be the change you wish to see in the world." - Mahatma Gandhi
|
|
|
|
|
quicksort for you, strait from Rotor.
private class SorterObjectArray
{
private Object[] keys;
private Object[] items;
private IComparer comparer;
public SorterObjectArray(Object[] keys, Object[] items, IComparer comparer) {
if (comparer == null) comparer = Comparer.Default;
this.keys = keys;
this.items = items;
this.comparer = comparer;
}
public virtual void QuickSort(int left, int right) {
do {
int i = left;
int j = right;
Object x = keys[(i + j) >> 1];
do {
try {
while (comparer.Compare(keys[i], x) < 0) i++;
while (comparer.Compare(x, keys[j]) < 0) j--;
}
catch (IndexOutOfRangeException) {
throw new ArgumentException(String.Format(Environment.GetResourceString("Arg_BogusIComparer"), x, x.GetType().Name, comparer));
}
catch (Exception e) {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
}
BCLDebug.Assert(i>=left && j<=right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
if (i > j) break;
if (i < j) {
Object key = keys[i];
keys[i] = keys[j];
keys[j] = key;
if (items != null) {
Object item = items[i];
items[i] = items[j];
items[j] = item;
}
}
i++;
j--;
} while (i <= j);
if (j - left <= right - i) {
if (left < j) QuickSort(left, j);
left = i;
}
else {
if (i < right) QuickSort(i, right);
right = j;
}
} while (left < right);
}
}
leppie::AllocCPArticle(Generic DFA State Machine for .NET);
|
|
|
|
|
Thanx. Looks like real qsort. Not as optimized as CRT, but still good enough. Thanx again.
|
|
|
|
|
Any reason you can't use the Array.Sort static method? I think that is the method that leppie gave the code from.
James
"I despise the city and much prefer being where a traffic jam means a line-up at McDonald's"
Me when telling a friend why I wouldn't want to live with him
|
|
|
|
|
|
I'm sure they will spell it correctly on the plagarism award.
|
|
|
|
|
|
I do wear glasses thank you. Perhaps you could recommend an Optometrist or you could write a dictionary for me( a copy www.m-w.com would be fine) Please respond so it boosts your posted rate, after all quantity certainly beats quality.
Sorry I forgot about the clickety police www.m-w.com[^]
|
|
|
|
|
Yes, I figured that out. Just couldn't find SorterObjectArray implementation in Reflector. Now it's ok. Thnx
|
|
|
|
|
I am trying to solve a problem with C# random. Using the standard implementation, I do not seem to be getting a random number. I often get patterns, and duplicates. I have even found a way to guarantee a different seed, instead of using DateTime.Now.Ticks or Environment.TickCount (code is below), but still get a patterned (a 5, then a 5 again) sequence. Can anybody help?
Random rdm1 = new Random(unchecked((int)DateTime.Now.Ticks) * Environment.TickCount);
byte[] random = new Byte[100];
//RNGCryptoServiceProvider is an implementation of a random number generator.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(keystore);
try
{
rng.GetBytes(random);
}
catch(CryptographicException e)
{
throw new ApplicationException("Random number generator threw an error:" + e.Message);
}
int seed = ~unchecked((int)DateTime.Now.Ticks) * Environment.TickCount * random[rdm1.Next(random.Length - 1)];
Random rdm2 = new Random(seed);
can anybody tell me what the Max range of RNGCryptoServiceProvider.GetBytes();
returns? In other words from the numbers in the byte array filled up what is the top number that can be in any one part of the array?
|
|
|
|
|
|
sIf you look at the code I am getting the first instance of Random to get a number randomly from the 'random' byte array, then using that number multiplied by Date.Now.Ticks and Environmemt.Ticks to generate the seed. If you run this as a test looping through for 100 iterations, you can see that the seed is always different, but that the integer generated by Random.Next(37) is not, and can be patterned. (I use 37b here so you get a small enough number to recognize the pattern.
|
|
|
|
|
OK, I'm replying here to track the code:
chris lasater wrote:
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(keystore);
OK, what is keystore? Why not use the default constructor?
chris lasater wrote:
can anybody tell me what the Max range of RNGCryptoServiceProvider.GetBytes();
It fills the byte[] to whatever length you initialized it (domain). The range is a byte, thus 0 to 255.
Now can you explain what you are trying to do? I still cant understand why you are not reusing the initial Random instance... Why random "data" do you need? And in what format/structure?
leppie::AllocCPArticle(Generic DFA State Machine for .NET);
|
|
|
|
|