| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -282,7 +282,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth | |||
| 282 | 282 | var pynargs = (int)Runtime.PyTuple_Size(args); | |
| 283 | 283 | object arg; | |
| 284 | 284 | var isGeneric = false; | |
| 285 | - ArrayList defaultArgList = null; | ||
| 286 | 285 | if (info != null) | |
| 287 | 286 | { | |
| 288 | 287 | _methods = new MethodBase[1]; | |
@@ -301,180 +300,151 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth | |||
| 301 | 300 | isGeneric = true; | |
| 302 | 301 | } | |
| 303 | 302 | ParameterInfo[] pi = mi.GetParameters(); | |
| 304 | - var clrnargs = pi.Length; | ||
| 305 | - var match = false; | ||
| 306 | - var arrayStart = -1; | ||
| 307 | - var outs = 0; | ||
| 303 | + ArrayList defaultArgList; | ||
| 304 | + int arrayStart; | ||
| 308 | 305 | ||
| 309 | - if (pynargs == clrnargs) | ||
| 310 | - { | ||
| 311 | - match = true; | ||
| 306 | + if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { | ||
| 307 | + continue; | ||
| 312 | 308 | } | |
| 313 | - else if (pynargs < clrnargs) | ||
| 309 | + var outs = 0; | ||
| 310 | + var margs = new object[pi.Length]; | ||
| 311 | + | ||
| 312 | + for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) | ||
| 314 | 313 | { | |
| 315 | - match = true; | ||
| 316 | - defaultArgList = new ArrayList(); | ||
| 317 | - for (var v = pynargs; v < clrnargs; v++) | ||
| 314 | + IntPtr op; | ||
| 315 | + if (paramIndex >= pynargs) | ||
| 318 | 316 | { | |
| 319 | - if (pi[v].DefaultValue == DBNull.Value) | ||
| 317 | + if (defaultArgList != null) | ||
| 320 | 318 | { | |
| 321 | - match = false; | ||
| 322 | - } | ||
| 323 | - else | ||
| 324 | - { | ||
| 325 | - defaultArgList.Add(pi[v].DefaultValue); | ||
| 319 | + margs[paramIndex] = defaultArgList[paramIndex - pynargs]; | ||
| 326 | 320 | } | |
| 321 | + | ||
| 322 | + continue; | ||
| 327 | 323 | } | |
| 328 | - } | ||
| 329 | - else if (pynargs > clrnargs && clrnargs > 0 && | ||
| 330 | - Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute))) | ||
| 331 | - { | ||
| 332 | - // This is a `foo(params object[] bar)` style method | ||
| 333 | - match = true; | ||
| 334 | - arrayStart = clrnargs - 1; | ||
| 335 | - } | ||
| 336 | 324 | ||
| 337 | - if (match) | ||
| 338 | - { | ||
| 339 | - var margs = new object[clrnargs]; | ||
| 325 | + if (arrayStart == paramIndex) | ||
| 326 | + { | ||
| 327 | + // map remaining Python arguments to a tuple since | ||
| 328 | + // the managed function accepts it - hopefully :] | ||
| 329 | + op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); | ||
| 330 | + } | ||
| 331 | + else | ||
| 332 | + { | ||
| 333 | + op = Runtime.PyTuple_GetItem(args, paramIndex); | ||
| 334 | + } | ||
| 340 | 335 | ||
| 341 | - for (int n = 0; n < clrnargs; n++) | ||
| 336 | + // this logic below handles cases when multiple overloading methods | ||
| 337 | + // are ambiguous, hence comparison between Python and CLR types | ||
| 338 | + // is necessary | ||
| 339 | + clrtype = null; | ||
| 340 | + IntPtr pyoptype; | ||
| 341 | + if (_methods.Length > 1) | ||
| 342 | 342 | { | |
| 343 | - IntPtr op; | ||
| 344 | - if (n < pynargs) | ||
| 343 | + pyoptype = IntPtr.Zero; | ||
| 344 | + pyoptype = Runtime.PyObject_Type(op); | ||
| 345 | + Exceptions.Clear(); | ||
| 346 | + if (pyoptype != IntPtr.Zero) | ||
| 345 | 347 | { | |
| 346 | - if (arrayStart == n) | ||
| 347 | - { | ||
| 348 | - // map remaining Python arguments to a tuple since | ||
| 349 | - // the managed function accepts it - hopefully :] | ||
| 350 | - op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); | ||
| 351 | - } | ||
| 352 | - else | ||
| 353 | - { | ||
| 354 | - op = Runtime.PyTuple_GetItem(args, n); | ||
| 355 | - } | ||
| 356 | - | ||
| 357 | - // this logic below handles cases when multiple overloading methods | ||
| 358 | - // are ambiguous, hence comparison between Python and CLR types | ||
| 359 | - // is necessary | ||
| 360 | - clrtype = null; | ||
| 361 | - IntPtr pyoptype; | ||
| 362 | - if (_methods.Length > 1) | ||
| 363 | - { | ||
| 364 | - pyoptype = IntPtr.Zero; | ||
| 365 | - pyoptype = Runtime.PyObject_Type(op); | ||
| 366 | - Exceptions.Clear(); | ||
| 367 | - if (pyoptype != IntPtr.Zero) | ||
| 368 | - { | ||
| 369 | - clrtype = Converter.GetTypeByAlias(pyoptype); | ||
| 370 | - } | ||
| 371 | - Runtime.XDecref(pyoptype); | ||
| 372 | - } | ||
| 348 | + clrtype = Converter.GetTypeByAlias(pyoptype); | ||
| 349 | + } | ||
| 350 | + Runtime.XDecref(pyoptype); | ||
| 351 | + } | ||
| 373 | 352 | ||
| 374 | 353 | ||
| 375 | - if (clrtype != null) | ||
| 354 | + if (clrtype != null) | ||
| 355 | + { | ||
| 356 | + var typematch = false; | ||
| 357 | + if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype)) | ||
| 358 | + { | ||
| 359 | + IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType); | ||
| 360 | + pyoptype = Runtime.PyObject_Type(op); | ||
| 361 | + Exceptions.Clear(); | ||
| 362 | + if (pyoptype != IntPtr.Zero) | ||
| 376 | 363 | { | |
| 377 | - var typematch = false; | ||
| 378 | - if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype)) | ||
| 364 | + if (pytype != pyoptype) | ||
| 379 | 365 | { | |
| 380 | - IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType); | ||
| 381 | - pyoptype = Runtime.PyObject_Type(op); | ||
| 382 | - Exceptions.Clear(); | ||
| 383 | - if (pyoptype != IntPtr.Zero) | ||
| 384 | - { | ||
| 385 | - if (pytype != pyoptype) | ||
| 386 | - { | ||
| 387 | - typematch = false; | ||
| 388 | - } | ||
| 389 | - else | ||
| 390 | - { | ||
| 391 | - typematch = true; | ||
| 392 | - clrtype = pi[n].ParameterType; | ||
| 393 | - } | ||
| 394 | - } | ||
| 395 | - if (!typematch) | ||
| 396 | - { | ||
| 397 | - // this takes care of enum values | ||
| 398 | - TypeCode argtypecode = Type.GetTypeCode(pi[n].ParameterType); | ||
| 399 | - TypeCode paramtypecode = Type.GetTypeCode(clrtype); | ||
| 400 | - if (argtypecode == paramtypecode) | ||
| 401 | - { | ||
| 402 | - typematch = true; | ||
| 403 | - clrtype = pi[n].ParameterType; | ||
| 404 | - } | ||
| 405 | - } | ||
| 406 | - Runtime.XDecref(pyoptype); | ||
| 407 | - if (!typematch) | ||
| 408 | - { | ||
| 409 | - margs = null; | ||
| 410 | - break; | ||
| 411 | - } | ||
| 366 | + typematch = false; | ||
| 412 | 367 | } | |
| 413 | 368 | else | |
| 414 | 369 | { | |
| 415 | 370 | typematch = true; | |
| 416 | - clrtype = pi[n].ParameterType; | ||
| 371 | + clrtype = pi[paramIndex].ParameterType; | ||
| 417 | 372 | } | |
| 418 | 373 | } | |
| 419 | - else | ||
| 374 | + if (!typematch) | ||
| 420 | 375 | { | |
| 421 | - clrtype = pi[n].ParameterType; | ||
| 422 | - } | ||
| 423 | - | ||
| 424 | - if (pi[n].IsOut || clrtype.IsByRef) | ||
| 425 | - { | ||
| 426 | - outs++; | ||
| 376 | + // this takes care of enum values | ||
| 377 | + TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType); | ||
| 378 | + TypeCode paramtypecode = Type.GetTypeCode(clrtype); | ||
| 379 | + if (argtypecode == paramtypecode) | ||
| 380 | + { | ||
| 381 | + typematch = true; | ||
| 382 | + clrtype = pi[paramIndex].ParameterType; | ||
| 383 | + } | ||
| 427 | 384 | } | |
| 428 | - | ||
| 429 | - if (!Converter.ToManaged(op, clrtype, out arg, false)) | ||
| 385 | + Runtime.XDecref(pyoptype); | ||
| 386 | + if (!typematch) | ||
| 430 | 387 | { | |
| 431 | - Exceptions.Clear(); | ||
| 432 | 388 | margs = null; | |
| 433 | 389 | break; | |
| 434 | 390 | } | |
| 435 | - if (arrayStart == n) | ||
| 436 | - { | ||
| 437 | - // GetSlice() creates a new reference but GetItem() | ||
| 438 | - // returns only a borrow reference. | ||
| 439 | - Runtime.XDecref(op); | ||
| 440 | - } | ||
| 441 | - margs[n] = arg; | ||
| 442 | 391 | } | |
| 443 | 392 | else | |
| 444 | 393 | { | |
| 445 | - if (defaultArgList != null) | ||
| 446 | - { | ||
| 447 | - margs[n] = defaultArgList[n - pynargs]; | ||
| 448 | - } | ||
| 394 | + typematch = true; | ||
| 395 | + clrtype = pi[paramIndex].ParameterType; | ||
| 449 | 396 | } | |
| 450 | 397 | } | |
| 398 | + else | ||
| 399 | + { | ||
| 400 | + clrtype = pi[paramIndex].ParameterType; | ||
| 401 | + } | ||
| 451 | 402 | ||
| 452 | - if (margs == null) | ||
| 403 | + if (pi[paramIndex].IsOut || clrtype.IsByRef) | ||
| 453 | 404 | { | |
| 454 | - continue; | ||
| 405 | + outs++; | ||
| 455 | 406 | } | |
| 456 | 407 | ||
| 457 | - object target = null; | ||
| 458 | - if (!mi.IsStatic && inst != IntPtr.Zero) | ||
| 408 | + if (!Converter.ToManaged(op, clrtype, out arg, false)) | ||
| 459 | 409 | { | |
| 460 | - //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); | ||
| 461 | - // InvalidCastException: Unable to cast object of type | ||
| 462 | - // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' | ||
| 463 | - var co = ManagedType.GetManagedObject(inst) as CLRObject; | ||
| 464 | - | ||
| 465 | - // Sanity check: this ensures a graceful exit if someone does | ||
| 466 | - // something intentionally wrong like call a non-static method | ||
| 467 | - // on the class rather than on an instance of the class. | ||
| 468 | - // XXX maybe better to do this before all the other rigmarole. | ||
| 469 | - if (co == null) | ||
| 470 | - { | ||
| 471 | - return null; | ||
| 472 | - } | ||
| 473 | - target = co.inst; | ||
| 410 | + Exceptions.Clear(); | ||
| 411 | + margs = null; | ||
| 412 | + break; | ||
| 474 | 413 | } | |
| 414 | + if (arrayStart == paramIndex) | ||
| 415 | + { | ||
| 416 | + // GetSlice() creates a new reference but GetItem() | ||
| 417 | + // returns only a borrow reference. | ||
| 418 | + Runtime.XDecref(op); | ||
| 419 | + } | ||
| 420 | + margs[paramIndex] = arg; | ||
| 421 | + } | ||
| 475 | 422 | ||
| 476 | - return new Binding(mi, target, margs, outs); | ||
| 423 | + if (margs == null) | ||
| 424 | + { | ||
| 425 | + continue; | ||
| 477 | 426 | } | |
| 427 | + | ||
| 428 | + object target = null; | ||
| 429 | + if (!mi.IsStatic && inst != IntPtr.Zero) | ||
| 430 | + { | ||
| 431 | + //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); | ||
| 432 | + // InvalidCastException: Unable to cast object of type | ||
| 433 | + // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' | ||
| 434 | + var co = ManagedType.GetManagedObject(inst) as CLRObject; | ||
| 435 | + | ||
| 436 | + // Sanity check: this ensures a graceful exit if someone does | ||
| 437 | + // something intentionally wrong like call a non-static method | ||
| 438 | + // on the class rather than on an instance of the class. | ||
| 439 | + // XXX maybe better to do this before all the other rigmarole. | ||
| 440 | + if (co == null) | ||
| 441 | + { | ||
| 442 | + return null; | ||
| 443 | + } | ||
| 444 | + target = co.inst; | ||
| 445 | + } | ||
| 446 | + | ||
| 447 | + return new Binding(mi, target, margs, outs); | ||
| 478 | 448 | } | |
| 479 | 449 | // We weren't able to find a matching method but at least one | |
| 480 | 450 | // is a generic method and info is null. That happens when a generic | |
@@ -489,6 +459,37 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth | |||
| 489 | 459 | return null; | |
| 490 | 460 | } | |
| 491 | 461 | ||
| 462 | + static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList) | ||
| 463 | + { | ||
| 464 | + defaultArgList = null; | ||
| 465 | + var match = false; | ||
| 466 | + paramsArrayStart = -1; | ||
| 467 | + | ||
| 468 | + if (pynargs == pi.Length) | ||
| 469 | + { | ||
| 470 | + match = true; | ||
| 471 | + } else if (pynargs < pi.Length) | ||
| 472 | + { | ||
| 473 | + match = true; | ||
| 474 | + defaultArgList = new ArrayList(); | ||
| 475 | + for (var v = pynargs; v < pi.Length; v++) { | ||
| 476 | + if (pi[v].DefaultValue == DBNull.Value) { | ||
| 477 | + match = false; | ||
| 478 | + } else { | ||
| 479 | + defaultArgList.Add(pi[v].DefaultValue); | ||
| 480 | + } | ||
| 481 | + } | ||
| 482 | + } else if (pynargs > pi.Length && pi.Length > 0 && | ||
| 483 | + Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute))) | ||
| 484 | + { | ||
| 485 | + // This is a `foo(params object[] bar)` style method | ||
| 486 | + match = true; | ||
| 487 | + paramsArrayStart = pi.Length - 1; | ||
| 488 | + } | ||
| 489 | + | ||
| 490 | + return match; | ||
| 491 | + } | ||
| 492 | + | ||
| 492 | 493 | internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw) | |
| 493 | 494 | { | |
| 494 | 495 | return Invoke(inst, args, kw, null, null); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments