C# délégué pour le C++ de rappel
Je pense que j'ai compris comment écrire c# délégués pour les rappels, mais celui-ci est source de confusion pour moi.
La définition c++ est comme suit:
typedef int (__stdcall* Callback)(
long lCode,
long lParamSize,
void* pParam
);
et mon c# approche serait:
unsafe delegate int CallbackDelegate (int lCode, int lParamSize, IntPtr pParam);
Bien que cela semble être incorrect, parce que je reçois un PInvokeStackInbalance d'erreur, ce qui signifie que ma définition du délégué est faux.
Le reste des paramètres de la fonction sont des chaînes de caractères ou des entiers, ce qui signifie qu'ils ne peuvent pas la cause de l'erreur, et si je viens de passer un IntPtr.Zéro à la place du délégué (ce qui voudrait dire que je suis pointant vers un inexistante fonction de rappel), je reçois un AccessViolation d'erreur, ce qui est logique, aswell.
Ce que je fais mal?
EDIT:
La pleine fonction c++:
int
__stdcall
_Initialize (
const char* FileName,
Callback cbFunction,
int Code,
const char* Name,
unsigned int Option,
unsigned int Option2
);
Ma version c# est:
[DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int _Initialize (string FileName, CallbackDelegate cbFunction, int Code, string Name, uint Options, uint Options2);
La fonction est (pour les tests) vient d'appeler à l'intérieur de la routine principale d'une application de console:
static void Main(string[] args)
{
CallbackDelegate del = new CallbackDelegate(onCallback);
Console.Write(_Initialize("SomeFile.dat", del, 1000, "", 0, 4));
Console.Read();
}
où onCallback
est-ce:
static int onCallback(int lCode, int lParamSize, IntPtr pParam)
{
return 0;
}
- Je obtenir le PInvokeStackInbalance
erreur sur la ligne où j'appelle _Initialize
, si je passe un IntPtr.Zero
au lieu de le déléguer, et de modifier la définition de la fonction de IntPtr
au lieu de CallbackDelegate
puis-je obtenir un AccessViolationException
.
The rest of the parameters of the function are strings or ints
. Ne pas masquer les informations.Avez-vous essayé utilisez pas dangereux? j'.e: délégué int CallbackDelegate(int lCode, int lParamSize, IntPtr pParam);
Je n'essaie pas de cacher des informations, j'ai essayé de faire des choses que je pas considéré comme pertinent. Je vais modifier la question et d'y ajouter les informations.
Juste essayé que maintenant, ne semble pas aider, soit
Modifier votre question avec votre code modifié pour prendre en compte les suggestions qui vous sont données. IntPtr au lieu de void* et entiers plutôt que de longs. Également inclure la façon dont vous appelez la fonction et à quel point vous êtes l'exception. Êtes-vous sur un 32 bits ou 64 bits du système?
OriginalL'auteur Valandur | 2012-11-29
Vous devez vous connecter pour publier un commentaire.
J'ai ajouté votre code pour mon projet actuel, où je fais beaucoup de C#/C++ interop dans VS2012. Et alors que je déteste utiliser le "cela a fonctionné sur ma machine", il a bien fonctionné pour moi. Le code que j'ai couru il est listé ci-dessous juste pour illustrer le fait que je n'ai pas fait et de changements fondamentaux.
Ma suggestion est que vous construire une nouvelle dll native avec un talon de fonction pour _Initialize comme ci-dessous et voir si cela fonctionne lorsque vous pouvez contrôler les deux côtés de l'interface. Si cela fonctionne, mais le réel dll n'a pas, c'est soit les paramètres du compilateur sur le natif de côté ou de leurs est un bug sur le natif de côté et c'est de buter sur la pile.
Sur le C#, côté, j'ai ajouté les déclarations à ma classe d'interface:
Et puis, dans ma main:
Qui est impair. Il sonne comme il ya une bonne chance qu'il ya un bug dans le C++ dll côté qui touche la pile. Est-il possible pour vous d'obtenir les sources pour le natif de dll sorte que vous pouvez les exécuter regroupés sous le débogueur? Je ne connais pas d'autre bonne façon de l'aborder, et il est presque certainement pas la manière à la FIXER avec la source.
Non, malheureusement je ne peux pas obtenir mes mains sur le code source, sinon je pense que ce serait beaucoup plus facile. J'ai essayé d'appeler la fonction c++ à partir d'un programme c++, et cela semble fonctionner parfaitement bien. À cet effet, je pense que la dll est bien, et je suis juste une erreur avec la fonction de rappel. Merci pour l'aide que.
OriginalL'auteur Wayne Tanner
Un .NET
long
est 64bits. C++long
peut être juste 32bits. Vérifier avec le compilateur C++ qui a compilé que la définition de la taille, il estlong
s sont.OriginalL'auteur Puppy
Si .NET suppose cdecl au lieu de stdcall, votre pile sera assurément arrosé.
OriginalL'auteur plinth