1

What I am trying to do is call a C++ method from Python to return a 2D array. The Python filename is: BaxterArm1.py and the C++ filename is: baxIK.cpp. Below is how I compiled my c++ program:

g++ -c -fPIC baxIK.cpp -o baxIK.o
g++ -shared -Wl,-soname,baxIK.so -o baxIK.so baxIK.o

Below is the relevant part of the C++ program:

int main(int argc, char** argv)
{

}

extern "C" float** compute(float x, float y, float z, float q1, float q2, float q3, float q4)
{
    unsigned int num_of_solutions = (int)solutions.GetNumSolutions();
    std::vector<IKREAL_TYPE> solvalues(num_of_joints);
    float** sols;
    sols = new float*[(int)num_of_solutions];

    for(std::size_t i = 0; i < num_of_solutions; ++i) {
        sols[i] = new float[7];
        for( std::size_t j = 0; j < solvalues.size(); ++j)
        {
            printf("%.15f, ", solvalues[j]);
            sols[i][j] = solvalues[j];
        }
        printf("\n");
    }   
    return sols;
}

The idea is to return a Nx7 array for Python to receive. The Python code is as follows:

def sendArm(xGoal, yGoal, zGoal, right, lj):
print "Goals %f %f %f" % (xGoal, yGoal, zGoal)
output = ctypes.CDLL(os.path.dirname('baxIK.so'))
output.compute.restype = POINTER(c_float)
output.compute.argtypes = [c_float, c_float, c_float, c_float, c_float, c_float, c_float]   
res = output.compute(xGoal, yGoal, zGoal, 0.707, 0, 0.7, 0)
print(res)

The error I get is on the line

output.compute.restype = POINTER(c_float)

and the traceback is below:

File "/home/eadom/ros_ws/src/baxter_examples/scripts/BaxterArm1.py", line 60, in sendArm
    output.compute.restype = POINTER(c_float)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 378, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 383, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: python: undefined symbol: compute

I'm confused as to how I'd fix this. Also, could somebody do a check on this and see if I'm sending the 2D array properly? As it is it's only sending a 1D array but I couldn't find anything on sending a 2D array. I'm grateful for any help.

13
  • 1
    The return type is pointer to pointer. Did you try output.compute.restype = POINTER(POINTER(c_float)) Commented Nov 25, 2015 at 4:30
  • Ah true, I will change that. Thank you. But that doesn't solve the other problem Commented Nov 25, 2015 at 4:52
  • 2
    You're using extern "C", so it shouldn't be name mangled. Check whether or not "compute" is listed in objdump -T baxIK.so, i.e. in the dynamic symbol table where dlsym looks for it. Commented Nov 25, 2015 at 10:03
  • I just did that. Compute shows up once but the overall terminal output is too long for the terminal to hold. Any other suggestions? Commented Nov 25, 2015 at 14:53
  • objdump -T baxIK.so | grep compute Commented Nov 25, 2015 at 15:06

1 Answer 1

0

Finally got it working! Problem is that (os.path.dirname('baxIK.so')was returning an empty string, so I put in the full directory. I fixed the other issue I mentioned earlier by compiling g++ with llapack and now I'm fixing up one last detail. I hope this helps somebody else.

Sign up to request clarification or add additional context in comments.

1 Comment

On POSIX systems CDLL('') references the main module. Because of the undefined symbol error, I didn't even notice that you were using dirname incorrectly. If the file is in the same directory as the script/module, you can use scriptdir = os.path.abspath(os.path.dirname(__file__)); libpath = os.path.join(scriptdir, 'baxIK.so').

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.