Могу ли я вызвать эту 32-битную DLL в 64-битном Python, используя межпроцессное взаимодействие? - PullRequest
1 голос
/ 29 марта 2019

Мне нужно вызвать 32-битную DLL из 64-битного Python, и у меня возникают проблемы с поиском хорошего примера использования межпроцессного взаимодействия. Мне не нужно пропускать или возвращать что-либо сложное. DLL для corpscon, который преобразует координаты в разные системы. Есть ли лучший способ обернуть 32-битную DLL. Я посмотрел на MSLoadlib, но у меня возникли проблемы с пониманием, как я буду загружать свою DLL с MSLoadlib.

Вот код,

from ctypes import *
import os

def conCoords(sysOutNum,outdatyear,outzonecode,inX,inY,inZ):
    corpslib = windll.LoadLibrary("C:\Program Files\CORPSCON6\corpscon_v6.dll")
    test00 = corpslib.corpscon_default_config()
    SetNadconPath = corpslib.SetNadconPath
    SetVertconPath = corpslib.SetVertconPath
    SetGeoidPath = corpslib.SetGeoidPath
    SetInSystem = corpslib.SetInSystem
    SetOutSystem = corpslib.SetOutSystem
    SetInDatum = corpslib.SetInDatum
    SetOutDatum = corpslib.SetOutDatum
    SetInZone = corpslib.SetInZone
    SetOutZone = corpslib.SetOutZone
    SetInUnits = corpslib.SetInUnits
    SetOutUnits = corpslib.SetOutUnits
    SetInVDatum = corpslib.SetInVDatum
    SetOutVDatum = corpslib.SetOutVDatum
    SetInVUnits = corpslib.SetInVUnits
    SetOutVUnits = corpslib.SetOutVUnits
    SetGeoidCodeBase = corpslib.SetGeoidCodeBase
    SetXIn = corpslib.SetXIn
    SetYIn = corpslib.SetYIn
    SetZIn = corpslib.SetZIn
    GetXOut = corpslib.GetXOut
    GetYOut = corpslib.GetYOut
    GetZOut = corpslib.GetZOut

    import ctypes

    SetNadconPath.argtypes = [ctypes.c_char_p]
    SetNadconPath.retval = [ctypes.c_int]
    SetVertconPath.argtypes = [ctypes.c_char_p]
    SetVertconPath.retval = [ctypes.c_int]
    SetGeoidPath.argtypes = [ctypes.c_char_p]
    SetGeoidPath.retval = [ctypes.c_int]
    SetInSystem.argtypes = [ctypes.c_int]  
    SetInSystem.retval = [ctypes.c_int]  
    SetInDatum.argtypes = [ctypes.c_int]  
    SetInDatum.retval = [ctypes.c_int]  
    SetOutDatum.argtypes = [ctypes.c_int]
    SetOutDatum.retval = [ctypes.c_int]
    SetOutSystem.argtypes = [ctypes.c_int]  
    SetOutSystem.retval = [ctypes.c_int]  
    SetInZone.argtypes = [ctypes.c_int]      
    SetInZone .retval = [ctypes.c_int]  
    SetOutZone.argtypes = [ctypes.c_int]    
    SetOutZone .retval = [ctypes.c_int] 
    SetInUnits.argtypes = [ctypes.c_int]  
    SetInUnits .retval = [ctypes.c_int]   
    SetInVDatum.argtypes = [ctypes.c_int]     
    SetInVDatum .retval = [ctypes.c_int]     
    SetOutVDatum.argtypes = [ctypes.c_int]    
    SetOutVDatum .retval =[ctypes.c_int]    
    SetInVUnits.argtypes = [ctypes.c_int]   
    SetInVUnits .retval = [ctypes.c_int]   
    SetOutVUnits.argtypes = [ctypes.c_int]    
    SetOutVUnits .retval = [ctypes.c_int]  
    SetGeoidCodeBase.argtypes = [ctypes.c_int]    
    SetGeoidCodeBase.retval = [ctypes.c_int]  
    SetXIn.argtypes = [ctypes.c_double]  
    SetXIn.retval = [ctypes.c_int]  
    SetYIn.argtypes = [ctypes.c_double]  
    SetYIn.retval = [ctypes.c_int]  
    SetZIn.argtypes = [ctypes.c_double]  
    SetZIn.retval = [ctypes.c_int]  
    GetXOut.retval =[ctypes.c_double]  
    GetYOut.retval =[ctypes.c_double]  
    GetZOut.retval = [ctypes.c_double]  

    test1 = SetNadconPath(r"C:\Program Files\CORPSCON6\Nadcon")
    test2 = SetVertconPath(r"C:\Program Files\CORPSCON6\Vertcon")
    test3 = SetGeoidPath(r"C:\Program Files\CORPSCON6\Geoid")

    ###################################
    ##
    ## Set Geographic or Stateplane
    ##
    ##################################
    sysInNum = 2 
    insys = SetInSystem(sysInNum)
    outsys = SetOutSystem(sysOutNum)

    ###################################
    ##
    ## Set Datum 83 or 27
    ##
    ##################################
    datumInYear = 1983
    indat = SetInDatum(datumInYear)
    datumOutYear = outdatyear
    outdat = SetOutDatum(datumOutYear)

    ###################################
    ##
    ## Set Zone ie 4202
    ##
    ##################################

    incode = 4202
    inzone = SetInZone(incode)

    outcode = outzonecode
    outzone = SetOutZone(outcode)

    ###################################
    ##
    ## Set Units
    ##
    ##################################

    units = 1

    outunits = SetOutUnits(units)
    inunits = SetInUnits(units)


    ###################################
    ##
    ## Set V Datum
    ##
    ##################################

    invdatum = SetInVDatum(1988)
    outvdatum = SetOutVDatum(1988)


    ###################################
    ##
    ## Set V Units
    ##
    ##################################

    invunits = SetInVUnits(1)
    outvunits = SetOutVUnits(1)

    geoidbase = SetGeoidCodeBase(2003)

    intcorpse = corpslib.corpscon_initialize_convert()

    #inX = 2790955
    #inY = 503380 
    #inZ = 2800.00

    xin = c_double(inX)
    yin = c_double(inY)
    zin = c_double(inZ)

    xout = c_double()
    yout = c_double()
    zout = c_double()

    SetXIn(xin)
    SetYIn(yin)
    SetZIn(zin)

    corpslib.corpscon_convert()

    corpslib.GetXOut.restype = c_double
    corpslib.GetYOut.restype = c_double
    corpslib.GetZOut.restype = c_double

    pntX = corpslib.GetXOut()
    pntY = corpslib.GetYOut()
    pntZ =  corpslib.GetZOut()



    return pntX,pntY,pntZ

x,y,z = conCoords(2,1983,4202,2790955,503380,2800.00)
print(x,y,z)

Корпус DLL находится здесь.

Corpscon.dll

1 Ответ

1 голос
/ 31 марта 2019

Вы можете использовать pywin32 для создания COM-сервера с использованием 32-разрядного Python, а затем использовать объект COM в 64-разрядном Python.

Вот небольшой китайский конвертер пиньинь, который я написал. Он принимает пронумерованный ввод, такой как wo3 shi4 mei3guo2ren2 и преобразует его в wǒ shì měiguórén:

_UMLAUT_U = u'\N{LATIN SMALL LETTER U WITH DIAERESIS}'

# tone number to combining diacritical table. 
_TONE = {u'1':u'\N{COMBINING MACRON}',
        u'2':u'\N{COMBINING ACUTE ACCENT}',
        u'3':u'\N{COMBINING CARON}',
        u'4':u'\N{COMBINING GRAVE ACCENT}',
        u'5':u''}

class Pinyin:
    _public_methods_ = ['Convert']
    _reg_progid_ = 'PythonUtil.Pinyin'
    _reg_clsid_ = '{3A7A52BA-3162-4fc1-8182-869258D2754D}'

    @staticmethod
    def _convert(matchobj):
        """_convert(matchobj) -> replacement text
        Helper function for re.sub with three groups.
        Group 1 - one or more vowels
        Group 2 - zero or more consonants
        Group 3 - tone character '1'-'5'
        Applies pinyin tone marks to the appropriate vowel.
        Algorithm:
        In vowels, replace 'v' with umlaut-u.
        First 'a' or 'e' in vowels gets the mark,
        else first 'ou', 'o' gets the mark,
        else last vowel gets the mark.
        """
        import unicodedata
        vowels,consonants,tone = matchobj.groups()
        vowels = vowels.replace(u'v',_UMLAUT_U)
        n = vowels.lower().find(u'a')
        if n == -1:
            n = vowels.lower().find(u'e')
        if n == -1:
            n = vowels.lower().find(u'ou')
        if n != -1:
            # a, e, or ou found.
            # Add accent after the a, e, or o
            retval = vowels[:n+1] + _TONE[tone] + vowels[n+1:] + consonants
        else:
            # accent after the last vowel
            retval = vowels + _TONE[tone] + consonants
        return unicodedata.normalize('NFC',retval)

    def Convert(self,pinyin_with_tone_numbers):
        """Convert(self,pinyin_with_tone_numbers) -> pinyin_with_tone_marks
        Given a pinyin string with tone numbers, return a converted unicode
        string with tone marks.  Requires 'v' to represent umlaut-u.
        """
        import re
        # Calls conversion function for each match.
        return re.sub(
            u'''(?ix)       # ignore case, verbose
            ([aeiouv]+)     # one or more vowels (v for umlaut-u)
            ([^aeiouv]*)    # zero or more non-vowels
            ([12345])       # tone mark 1-5
            ''',self._convert,pinyin_with_tone_numbers)

if __name__ == '__main__':
    import win32com.server.register
    win32com.server.register.UseCommandLine(Pinyin)

Запустите приведенный ниже скрипт, чтобы зарегистрировать COM-сервер, используя 32-битный Python, а затем в 64-битном Python:

>>> import win32com.client
>>> s=win32com.client.Dispatch('PythonUtil.Pinyin')
>>> s.Convert('wo3 shi4 mei3guo2ren2')
'wǒ shì měiguórén'

При необходимости адаптируйтесь к вашему приложению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...