I don't think you need so many transients set, one for each category. You can only use one, that is enough. Transients are quite expensive to set as it requires additional db queries, so you would want to cut down on the use.

As always, I like to keep my templates simple, short and sweet, so I tend to write custom functions to move the bulk of the code outside my templates. You can put everything in one function with one transient

You can try something like this (Requires PHP 5.4+)

function get_term_post_list( $taxonomy = 'category', $args = [], $query_args = [] )  
{
    /*
     * Check if we have a transient set
     */
    if ( false === ( $output = get_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ) ) ) ) {

        /*
         * Use get_terms to get an array of terms
         */
        $terms = get_terms( $taxonomy, $args );

       if ( is_wp_error( $terms ) || empty( $terms ) )
            return null;

        /*
         * We will create a string with our output
         */
        $output = ''; 
        foreach ( $terms as $term ) {

            $output .= '&lt;div class="subject"&gt;';
            $output .= '&lt;h3&gt;' . $term-&gt;name . '&lt;/h3&gt;';
            $output .= '&lt;ul&gt;';

            /*
             * Use a tax_query to make this dynamic for all taxonomies
             */
            $default_args = [
                'no_found_rows' =&gt; true,
                'suppress_filters' =&gt; true,
                'tax_query' =&gt; [
                    [
                        'taxonomy' =&gt; $taxonomy,
                        'terms' =&gt; $term-&gt;term_id,
                        'include_children' =&gt; false
                    ]
                ]
            ];
            /*
             * Merge the tax_query with the user set arguments
             */
            $merged_args = array_merge( $default_args, $query_args );

            $q = new WP_Query( $merged_args );

            while($q-&gt;have_posts()) {
                $q-&gt;the_post();

                $output .= '&lt;li&gt;&lt;a href="' . get_permalink() . '" title="' . apply_filters( 'the_title', get_the_title() ) . '"&gt;' . apply_filters( 'the_title', get_the_title() ) . '&lt;/a&gt;&lt;/li&gt;';

            }
            wp_reset_postdata();

            $output .= '&lt;/ul&gt;';
            $output .= '&lt;/div&gt;';

        }
        /*
         * Set our transient, use all arguments to create a unique key for the transient name
         */
        set_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ), $output, 36 * HOUR_IN_SECONDS );
    }
    /*
     * $output will be atring, treat as such
     */
    return $output;
}


FEW NOTES


The first parameter, $taxonomy is the taxonomy to get terms and posts from. It defaults to 'category'
The second parameter is $args which is the arguments which should be passed to get_terms(). For more info, check get_terms()
The third parameter, $query_args is the arguments that should be passed to the custom query. Remember to avoid using any taxonomy related parameters. For more info, see WP_Query
If the second parameter is not set and the third parameter is set, pass an empty array to the second parameter
Modify and abuse the code as you see fit


USAGE

You can now use the function as follow in your templates

$post_list = get_term_post_list( 'category', ['exclude' =&gt; '1, 4, 9, 10, 2899'], ['posts_per_page' =&gt; 3] );
if ( $post_list !== null ) {
    echo $post_list;
}


If you do not pass anything to the second parameter but to the third, you should do the following (pass empty array)

$post_list = get_term_post_list( 'category', [], ['posts_per_page' =&gt; 3] );
if ( $post_list !== null ) {
    echo $post_list;
}


EDIT

In a rush, I totally forgot to add a function to flush the transient when a new post is published, updated, deleted or undeleted. As your code stands, the list will only be updated when the transient expires. 

To flush the transient on the above post conditions, simply use the transition_post_status hook. Add the following to your functions.php

add_action( 'transition_post_status', function ()
{
        global $wpdb;
        $wpdb-&gt;query( "DELETE FROM $wpdb-&gt;options WHERE `option_name` LIKE ('_transient%_term_list_%')" );
        $wpdb-&gt;query( "DELETE FROM $wpdb-&gt;options WHERE `option_name` LIKE ('_transient_timeout%_term_list_%')" );
});


EDIT 2

From your comment to this answer


  As you might have guessed I'd liked to use this in combination with my other question. How would I go about doing that? Should the exclusion of the terms happen in get_term_post_list()? Or should the two functions be merged somehow? (As I don't need them seperately.) 


The best way to accomplish is to merge the two functions into one. That would make the most sense. I have merged the two functions and modified the functionality with the exclude parameters. What I have done is, you can now add an array of term id's to excludse via the get_terms() exclude parameter and you can also within the same function set an array of term slugs to exclude. The results will be merged into one single exclude parameter before being passed to get_terms()

Here is the function, again I have commented it well to make it easy to follow (This goes into functions.php)

function get_term_post_list( $taxonomy = 'category', $args = [], $query_args = [], $exclude_by_slug = [] )  
{
    /*
     * Check if we have a transient set
     */
    if ( false === ( $output = get_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ) ) ) ) {

        /*
         * Check if any array of slugs is passed and if it is a valid array
         */
        if ( is_array( $exclude_by_slug ) &amp;&amp; !empty( $exclude_by_slug ) ) {

            foreach ( $exclude_by_slug as $value ) {

                /*
                 * Use get_term_by to get the term ID and add ID's to an array
                 */
                $term_objects = get_term_by( 'slug', $value, $taxonomy );
                $term_ids[] = (int) $term_objects-&gt;term_id;

            }

        }

        /*
         * Merge $args['exclude'] and $term_ids 
         */
        if ( isset( $args['exclude'] ) &amp;&amp; isset( $term_ids ) ) {

            $excluded_args = (array) $args['exclude'];
            unset( $args['exclude'] );
            $args['exclude'] = array_merge( $excluded_args, $term_ids );

        } elseif ( !isset( $args['exclude'] ) &amp;&amp; isset( $term_ids ) ) {

            $args['exclude'] = $term_ids;

        } 

        /*
         * Use get_terms to get an array of terms
         */
        $terms = get_terms( $taxonomy, $args );

       if ( is_wp_error( $terms ) || empty( $terms ) )
            return null;

        /*
         * We will create a string with our output
         */
        $output = ''; 
        foreach ( $terms as $term ) {

            $output .= '&lt;div class="subject"&gt;';
            $output .= '&lt;h3&gt;' . $term-&gt;name . '&lt;/h3&gt;';
            $output .= '&lt;ul&gt;';

            /*
             * Use a tax_query to make this dynamic for all taxonomies
             */
            $default_args = [
                'no_found_rows' =&gt; true,
                'suppress_filters' =&gt; true,
                'tax_query' =&gt; [
                    [
                        'taxonomy' =&gt; $taxonomy,
                        'terms' =&gt; $term-&gt;term_id,
                        'include_children' =&gt; false
                    ]
                ]
            ];
            /*
             * Merge the tax_query with the user set arguments
             */
            $merged_args = array_merge( $default_args, $query_args );

            $q = new WP_Query( $merged_args );

            while($q-&gt;have_posts()) {
                $q-&gt;the_post();

                $output .= '&lt;li&gt;&lt;a href="' . get_permalink() . '" title="' . apply_filters( 'the_title', get_the_title() ) . '"&gt;' . apply_filters( 'the_title', get_the_title() ) . '&lt;/a&gt;&lt;/li&gt;';

            }
            wp_reset_postdata();

            $output .= '&lt;/ul&gt;';
            $output .= '&lt;/div&gt;';

        }
        /*
         * Set our transient, use all arguments to create a unique key for the transient name
         */
        set_transient( 'term_list_' . md5( $taxonomy . json_encode( $args ) . json_encode( $query_args ) ), $output, 36 * HOUR_IN_SECONDS );
    }
    /*
     * $output will be string, treat as such
     */
    return $output;
}


As far as usage, you first need to look at the parameters that you can pass


Parameter 1 - $taxonomy -> taxonomy to get terms from. Default category
Parameter 2 - $args -> The arguments that should be passed to get_terms(). Please see get_terms() for a full list of parameters that can be passed as an array. Default empty array []
Parameter 3 - $query_args -> Custom argument to be passed to WP_Query. You should not pass taxonomy related parameters here as it cause issues with the deafult build in tax_query. For a full list of valid arguments which can be passed in an array, see WP_Query. Default empty array []
Parameter 4 - $exclude_by_slug -> An array of slugs to exclude. Please note, this has to be a valid array for this to work. Strings will be ignored. Default empty array []


You can now call the function in any of your template files as

$a = get_term_post_list( 'category', ['exclude' =&gt; [1, 13, 42]], ['posts_per_page' =&gt; 3], ['term-slug-1', 'term-slug-2'] );
echo $a;


OR

$taxonomy = 'category';
$args = [
    'exclude' =&gt; [1, 13, 42]
];
$query_args = [
    'posts_per_page' =&gt; 3
];
$exclude_by_slug = [
    '0' =&gt; ['term-slug-1', 'term-slug-2']
];
$a = get_term_post_list( $taxonomy, $args, $query_args, $exclude_by_slug );
echo $a;


Final note, if you don't need to pass a specific parameter, remember to just pass an empty array like

$a = get_term_post_list( 'category', [], [], ['term-slug-1'] );
echo $a;


All the above replaces all your code in your question

Looping through posts per category gives same posts for each category
I'm trying to create a dynamic library in Rust that exports a struct as a symbol that will be loaded into a C program via dlopen().

However, I'm was running into some segfaults when accessing the second string in the struct, so I made a small test program to try figure out what I'm doing wrong.

This is the Rust code (test.rs), compiled with "rustc --crate-type dylib test.rs":

#[repr(C)]
pub struct PluginDesc {
    name: &amp;'static str,
    version: &amp;'static str,
    description: &amp;'static str
}


#[no_mangle]
pub static PLUGIN_DESC: PluginDesc = PluginDesc {
    name: "Test Plugin\0",
    version: "1.0\0",
    description: "Test Rust Plugin\0"
};


and here is the C program that attempts to load the library (test.c), compiled with "gcc test.c -ldl -o test":

#include &lt;dlfcn.h&gt;
#include &lt;stdio.h&gt;


typedef struct {
    const char *name;
    const char *version;
    const char *description;
} plugin_desc;


int main(int argc, char **argv) {
    void *handle;
    plugin_desc *desc;

    handle = dlopen("./libtest.so", RTLD_LOCAL | RTLD_LAZY);
    if (!handle) {
        printf("failed to dlopen: %s\n", dlerror());
        return 1;
    }

    desc = (plugin_desc *) dlsym(handle, "PLUGIN_DESC");
    if (!desc) {
        printf("failed to dlsym: %s\n", dlerror());
        return 1;
    }

    printf("name: %p\n", desc-&gt;name);
    printf("version: %p\n", desc-&gt;version);
    printf("description: %p\n", desc-&gt;description);

    return 0;
}


This is the output:

name: 0x7fa59ef8d750
version: 0xc
description: 0x7fa59ef8d75c


As you can see, the address of desc->version is actually 0xc (12), which is the length of the first string. So it looks like the struct that gets packed into the library also contains the string length after the memory address.

Am I using the wrong string type here? As you can see I had to also make the strings NULL terminated manually. I tried to use the CString wrapper but that does not seem to work in this case ("static items are not allowed to have destructors").

I'm running the latest Rust nightly on Linux:

$ rustc --version
rustc 0.12.0-pre-nightly (f8426e2e2 2014-09-16 02:26:01 +0000)

